第5.1章: 内存与地址
概述
在讨论指针之前,我们需要一个关于内存的简单心智模型。 在本章中,“内存”只是一段很长的字节序列,每个字节 都有一个编号,称为它的地址。
你可以把内存想象成一条有着一排房子的街道:
Address: 1000 1001 1002 1003 1004 1005 1006 1007
Memory: [ ?? ] [ ?? ] [ ?? ] [ ?? ] [ ?? ] [ ?? ] [ ?? ] [ ?? ]
↑
a byte at address 1000
你程序中的每个对象(整数、double、容器等) 都位于这条“街道”上的某处,并占用一个或多个字节。
对象与它们的内存
当你创建一个变量时,编译器会在内存中为它预留空间。 变量的值存储在这块空间里,而它的地址 就是它所用第一个字节的编号。
示例:一个简单的整数
int x{42};
假设 x 使用从地址 2000 开始的 4 个字节:
Address: 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
Memory: .... .... .... .... [ 42 ][ 42 ][ 42 ][ 42 ] .... ....
↑
x starts here
你不需要真实的数字;这只是一个模型。 关键在于:每个对象都占用一些字节,而这些字节都有一个地址。
容器同样位于内存中
在第4章中,你接触了 ::fast_io::string、
::fast_io::vector 和 ::fast_io::array。
它们也是对象,因此同样占用内存空间。
示例:::fast_io::array
::fast_io::array a{10, 20, 30, 40};
你可以这样想象它:
Address: 3000 3004 3008 3012
Memory: [ 10 ] [ 20 ] [ 30 ] [ 40 ]
↑
a[0] starts here
元素在内存中一个接一个地存放。实际的地址 由编译器和系统决定,但它们构成一个连续的块。
string 与 vector:对象加上元素
::fast_io::string 和 ::fast_io::vector 要更复杂一些。
它们是管理着一块独立内存的对象,元素就存放在那块内存里。
示例:::fast_io::string
::fast_io::string s{"Hello"};
你可以这样描绘它:
(object s) (characters managed by s)
Address: 4000 4008 4016 5000 5001 5002 5003 5004
Memory: [ ... s header ... ] [ 'H' ][ 'e' ][ 'l' ][ 'l' ][ 'o' ]
↑ ↑
s lives here first character lives here
“头部”的细节暂时不重要。关键思想是: string 对象有自己的地址,而它所管理的字符 也有各自的地址。
示例:::fast_io::vector
::fast_io::vector v{1, 2, 3};
(object v) (elements managed by v)
Address: 6000 6008 6016 7000 7004 7008
Memory: [ ... v header ... ] [ 1 ][ 2 ][ 3 ]
↑ ↑
v lives here v[0] lives here
同样,重点在于容器对象与它所管理的元素 都占用内存中的某处空间。
为什么我们关心地址
在第5章余下的部分,我们将使用指针。
指针就是存储地址的变量,例如一个 int 的地址,
或者 ::fast_io::vector 或 ::fast_io::array 中
第一个元素的地址。
这个关于内存与地址的简单模型将帮助你理解:
- 如何询问一个对象“住在哪里”
- 如何顺着一个地址去访问某个对象
data()之类的容器函数与内存有何关系
在下一章(第5.2章)中,我们将正式介绍指针, 并看看它们如何存储和使用这些地址。
要点
- 内存是一段很长的字节序列,每个字节都有一个地址。
- 你程序中的每个对象都在内存中占用若干字节。
- 对象的地址就是它第一个字节的编号。
::fast_io::array把元素直接连续存放在对象内部。::fast_io::vector和::fast_io::string除了自身的对象存储之外,还有一块独立的内存用于存放元素。- 容器对象与它所管理的元素都位于内存中的某处。
- 本章的内存模型为你理解指针(它存储这些地址)做好了准备。