【发布时间】:2015-11-09 16:08:29
【问题描述】:
以下定义是否明确?
#include <iostream>
#include <string.h>
using namespace std;
struct Const {
const int i;
Const (int i) : i(i) {}
int get0() { return 0; } // best accessor ever!
};
int main() {
Const *q,*p = new Const(1);
new (p) Const(2);
memcpy (&q, &p, sizeof p);
cout << q->i;
return 0;
}
请注意,在构造第二个Const 之后,p 不会在语义上(故意?)指向新对象,并且第一个已经消失,因此它可以“作为void*”使用。但是第二个对象是在完全相同的地址构造的,所以p的位模式代表了新对象的地址。
评论
new (p) Const(2) 擦除存储在p 的旧对象,因此该指针不再有效,除非作为指向存储的指针 (void*)。
我想将p 的值恢复为Const*。
评论 2
在p->~Const() 或memset (p, 0, sizeof *p) 之后,很明显p 不指向有效对象,因此p 只能用作指向存储的指针(void* 或char*),对于例如重建另一个对象。此时,p->get0() 是不允许的。
这里旧对象的拆除是由新对象的构造函数完成的,但我认为这没有什么区别。
我的直觉是:无论如何,旧对象已经消失了,p 指向的是旧对象,而不是新对象。
我正在寻找基于标准的确认或反驳。
另见
我在 C 和 C++ 中问过关于指针的基本相同的问题:
- Dereferencing an out of bound pointer that contains the address of an object (array of array)
- Is memcpy of a pointer the same as assignment?
- Are pointer variables just integers with some operators or are they "mystical"?
在回答“这很荒谬”之前,请阅读这些讨论。
【问题讨论】:
-
memcpy应该等价于q = p简单的指针赋值,不是吗? -
"赋值复制指针值,我只想复制它的位模式。"指针值是您使用 memcpy 复制的位的值。
-
N4430 解决了类似的问题。
-
@curiousguy 有人可能会争辩说,未初始化的
int是无效的,因为它是 UB 读取它。但是一旦初始化,它仍然有效。 -
@ChrisBeck:原始对象的析构函数没有被调用......只要程序的其余部分不依赖于析构函数的副作用,它就没有未定义的行为。请参阅 3.8/1 “T 类型对象的生命周期在以下情况下结束:...对象占用的存储空间被重用或释放”,以及 3.8/4 的 “任何依赖于关于析构函数产生的副作用有未定义的行为”.
标签: c++ constants language-lawyer memcpy placement-new