提问人:Luchian Grigore 提问时间:7/31/2012 更新时间:7/31/2012 访问量:192
先前初始化的内存是否保证在放置新调用后仍然存在?
Is previously initialize memory guaranteed to persist after a placement new call?
问:
假设我有以下内容:
struct A
{
int x;
};
//...
A* aOriginal = new A(); //value construct aOriginal
assert( aOriginal->x == 0 );
A* aSecond = new (aOriginal) A;
assert( aSecond->x == 0 );
第二个断言是否保证成立,即使没有初始化值?从逻辑上讲,它应该,因为内存没有被覆盖,但它是由标准指定的吗?aSecond
答:
9赞
R. Martinho Fernandes
7/31/2012
#1
不。
在同一存储位置构造第二个对象时,前一个对象的生存期结束 (§3.8/1):
[...]在以下情况下,该类型的对象的生存期结束:
T
- 如果是具有非平凡析构函数 (§12.4) 的类类型,则析构函数调用将启动,或者
T
- 对象占用的存储被重用或释放。
创建第二个对象时,由于具有隐式默认构造函数,因此该成员是默认初始化的,因此不执行初始化 (§8.5/6):A
x
默认初始化类型的对象意味着:
T
[...]
否则,不执行初始化。
这意味着对象具有不确定的值 (§5.3.4/15):
创建类型对象的 new-expression 将初始化该对象,如下所示:
T
- 如果省略 new-initializer,则对象默认初始化 (§8.5);如果未执行初始化, 对象具有不确定的值。
如果您认为该值不是不确定的,因为您之前在该存储位置上初始化了另一个对象:标准也放弃了这种可能性,因为它说前一个对象的属性在其生命周期结束后不再适用 (§3.8/3):
本国际标准中赋予对象的属性仅适用于给定对象在其生命周期内。
评论
1赞
David Rodríguez - dribeas
7/31/2012
我认为问题在于,不初始化是否意味着内存保证不会被修改。由于正在使用 placement new,因此他想知道是否可以依赖在构造新对象后未修改的值。
2赞
R. Martinho Fernandes
7/31/2012
@DavidRodríguez,我认为“不确定的价值”很清楚,你不能依赖它。
1赞
GManNickG
7/31/2012
我认为这里的歧义在于“不确定”这个词,它从未真正定义过。它的意思是“始终被认为是未初始化的”,还是意味着“除非以前初始化,否则被认为是未初始化的”?我们知道使用未初始化的值是未定义的行为,但它没有说明使用不确定的值。
1赞
R. Martinho Fernandes
7/31/2012
@GManNickG即使它不是 UB,也不能保证断言通过。FWIW(可能不多):§17.6.3.4 上还有一条注释,说“涉及不确定值的操作可能会导致未定义的行为。更具体地说,我相信在这些情况下,允许实现写入特殊值,例如用于调试。
2赞
R. Martinho Fernandes
7/31/2012
@VladLazarenko问题在于这是否得到标准保证。我不明白你在那里想说什么。
上一个:关于 C++ 优化的问题
下一个:在函数签名中指定结构
评论