在C ++中:
const size_t N = 1000;
int* p = new int[N];// time=t0
我的程序只有一个线程,在将内存分配给p
之后,我的程序将只读取p
指向的内存。
标准对p
的价值有什么看法?
p
将delete
p
p
保持N
时保持得到的值?
或者,操作系统可以自行决定重新分配{{1}}指向的内存吗?
是否取决于{{1}}的价值?
答案 0 :(得分:5)
p的值在创建后无法移动。该标准使得这样做毫无用处:
3.7.4.1分配功能
...如果请求成功,返回的值应为非空指针值(4.10)p0不同于任何 先前返回值p1,除非随后将值p1传递给运算符delete。
(引用标准的结尾)
因此,如果在运行时由于合并某些内存片段等原因决定将p移动到另一个地址,则该标准使得原始p指向的空间不可能被另一个内存分配使用。这个空间将被浪费掉。
答案 1 :(得分:1)
标准的内存模型和预期语义说明了实现必须符合的可观察行为(参见第1.7节 - C ++内存模型 - 到1.10 - 多线程执行和数据竞争 - 标准( 1))。此可观察行为应与标准中描述的抽象机器匹配。它特别将程序的存储器定义为一组字节序列,可以通过副作用操作(存储器上的I / O)来修改。指针本身是存储在存储器中的字节序列,因此遵循相同的规则。该模型还指定了未定义行为的情况,可能发生任何事情,包括内存损坏。此外,多线程程序可以通过竞争条件(见1.10)修改内存"在它自己的后面" (我自己的措辞,而不是实际的引用)。
new
运算符通过使用返回内存地址的分配函数来工作,并且还必须遵守可观察行为的规则。
话虽如此,第1.9段(计划执行)在第8点中指出,在符合要求的实施的最低要求中,:
严格按照抽象机的规则评估对volatile对象的访问。
换句话说,虽然程序应该呈现与标准中描述的模型所证明的相同的结果,但只有volatile
可以保证完全按照标准描述它来观察。非易失性存储可能无法以一致的方式观察到(如果您已经在优化代码上使用了调试器,则可以清楚地看到内存内容更新中的奇怪模式与程序源实际指定的内容有关)。
另一个重要的一点是new
运算符是可重载的,这意味着标准中描述的默认行为可能会有所改写。如果标准的最低限度执行(即,仅执行volatile
变量观察)仅运行new
已被覆盖并且不依赖volatile
数据来跟踪其内存堆,优化和强内联,返回指针的值可能不会立即在存储它们的变量中可见。如果优化通过确定变量生命周期可以从程序描述的内容缩短,那么也可以重新利用与该变量相对应的存储器位置,并且可以在调试器中更改和观察其内容,尽管程序没有指示这样的更新。然而,编译器的工作是确保程序的执行符合预期的行为:从程序的角度来看,变量将在其整个生命周期中保持其值,并且除非程序< em>以内存模型允许的任何方式通过更新指定。
在您的示例中,如果您在程序中p
分配之后多次访问变量new
,则您不会注意到值的更改它包含自该分配以来,标准需要它。如果您尝试通过某个外部设备观察该变量的内存位置,则可以跳出标准的抽象内存模型,并可能看到其内容发生变化。
(1)使用修订版N3485作为参考,段落编号可能在以后的修订版中有所改变。 子>
答案 2 :(得分:0)
p的值只是一个内存位置。分配后不会更改。它指向的内存可以改变。它不会被操作系统改变。它可以由您的程序更改。如果只是简单地分配一个整数数组(例如),并为每个整数赋值。您可以放心,除非您明确覆盖它们(或者有一个错误,否则这些值不会改变。)
答案 3 :(得分:0)
堆分配的地址将保持不变,变量不会在没有您影响的情况下更改其值。您的p
甚至会在删除后保留其值,但如果您尝试访问它,则会触发(希望)分段错误。 N
的值不起作用。