在C++中:
const size_t N = 1000;
int* p = new int[N];// time=t0
我的程序只有一个线程,在为p分配内存后,程序将仅读取由p指向的内存。
标准对p的值有何规定? p在t0时刻获得的值会一直保留到delete p吗?
或者,操作系统可以自行重新分配由p指向的内存吗?
这是否取决于N的值?
在C++中:
const size_t N = 1000;
int* p = new int[N];// time=t0
创建后,变量p的值不能被移动。标准规定这样做是没有意义的:
3.7.4.1 分配函数
......如果请求成功,返回的值将是一个非空指针值(4.10)p0,与以前返回的值p1不同,除非该值p1随后被传递给operator delete。
(引用标准结束)
因此,如果在运行时决定将p移动到另一个地址,以便于合并一些内存片段等原因,标准规定原始p所指向的空间不能被其他内存分配所使用,这个空间将被浪费。
new
运算符通过使用分配函数工作,该函数返回内存地址,并且也必须遵守可观察行为的规则。volatile
能够按照标准精确地被观察到。非易失性存储可能不会以一致的方式被观察到(如果您已经在优化代码上使用了调试器,则可以清楚地看到与程序源实际指定的内容更新相关的奇怪模式)。
另一个重要的点是new
运算符是可重载的,这意味着标准描述的默认行为可能会被覆盖。如果标准的最小兼容实现(即,仅强制执行volatile
变量观察)运行了一个已经被重载并且不依赖于volatile
数据来跟踪其内存堆的程序,并且进行了优化和强大的内联操作,那么返回指针的值可能不会立即在存储它们的变量中可见。如果优化传递确定变量的生命周期可以从程序描述的时间缩短,那么对应于该变量的内存位置可能被重新分配并更改其内容,并且在调试器中观察到此类更改,尽管程序没有指示这样的更新。然而,编译器的工作是确保程序的执行符合预期的行为:从程序的角度来看,变量将在其整个生命周期内保持其值,并且除非程序通过内存模型允许的任何方式进行更新,否则不会更改。new
分配之后多次访问变量p
,你不会注意到自该赋值以来它所包含的值的变化,这是标准要求的。如果您尝试通过某些外部设备观察该变量的内存位置,则会跳出标准的抽象内存模型,并可能目睹其内容的更改。p的值只是一个内存位置。一旦被赋值,它就不会改变。它所指向的内存可以改变,但不会被操作系统更改,只能由程序更改。如果你只是分配了一个整数数组(例如),并为每个整数赋值,那么你可以放心,除非你明确地覆盖它们(或者有一个错误这样做),否则这些值不会改变。
p
也将保持其值,但如果你尝试访问它,你将触发(希望如此)一个分段错误。变量 N
的值并不起作用。
p
可以保持其值,并且由p
指向的内存可以被重新分配。 - juanchopanza