最近我遇到了这两种在内存中特定位置创建对象的方法:
1。
void* mem = malloc(sizeof(T));
T* obj = new(mem) T();
2.
T* obj = (T*)malloc(sizeof(T));
*obj = T();
第二种方式有点短……还有其他区别吗?问候马特乌斯
最近我遇到了这两种在内存中特定位置创建对象的方法:
1。
void* mem = malloc(sizeof(T));
T* obj = new(mem) T();
2.
T* obj = (T*)malloc(sizeof(T));
*obj = T();
第二种方式有点短……还有其他区别吗?问候马特乌斯
第二种方式是错误的,第一种是正确的。
您正在对包含垃圾数据的 T 实例调用赋值运算符。赋值运算符希望实例已正确初始化 - 例如,它可以在赋值之前删除成员变量,这会导致各种有趣的崩溃。参见例如:
struct Foo {
std::string * Data;
Foo() : Data(0) {}
Foo(Foo const & R) { Data = new std::string(*R.Data); }
~Foo() { delete Data; }
Foo & operator=(Foo const & R) {
delete Data;
Data = new std::string(*R.Data);
return *this;
}
};
第一种方法将确保Foo::Foo()
被调用 - 从而正确初始化Data
。第二种方式将导致delete Data;
whereData
指向内存中的某个随机位置。
编辑:
您可以通过以下方式对此进行测试:
void* mem = malloc(sizeof(Foo));
memset(mem, 0xCC, sizeof(Foo)); // malloc doesn't guarantee 0-init
Foo* obj = new(mem) Foo();
和:
Foo * obj = (Foo*)malloc(sizeof(Foo));
memset(obj, 0xCC, sizeof(Foo)); // malloc doesn't guarantee 0-init
*obj = Foo(); // Crash
*obj = T();
该语句T
在堆栈上构造一个对象,然后对*obj
. 它带来了意想不到的后果。
另一方面,
T* obj = new (mem) T();
该语句按预期mem
通过执行构造函数方法初始化指定的内存缓冲区。T()