C++ 中放置 new VS 显式构造函数调用

发布于 2024-10-21 16:54:32 字数 251 浏览 7 评论 0原文

最近我遇到了这两种在内存中特定位置创建对象的方法:
1.

void* mem = malloc(sizeof(T));
T* obj = new(mem) T();


2.

T* obj = (T*)malloc(sizeof(T));
*obj = T();

第二种方式有点短...还有其他区别吗? 问候 马特乌什

recently I have come across these two ways of creating an object in a specific place in memory:

1.

void* mem = malloc(sizeof(T));
T* obj = new(mem) T();

2.

T* obj = (T*)malloc(sizeof(T));
*obj = T();

The second way is a bit shorter...are there other differences?
Regards
Mateusz

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小帐篷 2024-10-28 16:54:32

第二种方法是错误的,第一种方法是正确的。

您正在包含垃圾数据的 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;,其中Data指向内存中的某个随机位置。

编辑:

您可以通过以下方式测试:

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

The second way is wrong, the first is right.

You're invoking the assignment operator on a T instance containg garbage data. The assignment operator expects the instance to have been initialized correctly - It could e.g. delete member variables before assigning, which would cause all sorts of funny crashes. See e.g:

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;
  }

};

The first way will ensure Foo::Foo() is called - thus properly initializing Data. The second way will lead to a delete Data; where Data points to some random location in memory.

EDIT:

You can test this the following way:

void* mem = malloc(sizeof(Foo));
memset(mem, 0xCC, sizeof(Foo)); // malloc doesn't guarantee 0-init
Foo* obj = new(mem) Foo();

And:

Foo * obj = (Foo*)malloc(sizeof(Foo));
memset(obj, 0xCC, sizeof(Foo)); // malloc doesn't guarantee 0-init
*obj = Foo(); // Crash
故事灯 2024-10-28 16:54:32
*obj = T();

此语句在堆栈上构造一个 T 对象,然后对 *obj 进行赋值。它会带来意想不到的后果。

另一方面,

T* obj = new (mem) T();

该语句按预期通过执行 T() 构造函数方法来初始化指定的内存缓冲区 mem

*obj = T();

This statement constructs a T object on the stack, and then does an assignment to *obj. It's wrought with unintended consequences.

On the other hand,

T* obj = new (mem) T();

This statement initializes a designated memory buffer, mem, by executing T() constructor method, as intended.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文