如何使用placementnew重新初始化字段

how to use placement new to reinitialize the field?

本文关键字:初始化 字段 何使用 placementnew      更新时间:2023-10-16

我的类包含字段:

private:
    OrderUpdate curOrderUpdate;

我一遍又一遍地使用它,它经常需要重新初始化:

for (int i = 0; i < entries.size(); i++) {
    auto entry = entries[i];
    new (&curOrderUpdate) OrderUpdate();
    curOrderUpdate.MDEntryID = entry.get_MDEntryID().value()[0];
            ...

我有几个问题:

  • 我可以使用变量吗?还是必须将其更改为指针?将OrderUpdate curOrderUpdate更改为OrderUpdate* curOrderUpdate
  • 赋值是强制性的吗?我应该写curOrderUpdate = new (&curOrderUpdate) OrderUpdate();还是只写new (&curOrderUpdate) OrderUpdate()就足够了

要回答您的具体问题:

  • 是的,您可以直接存储对象(而不是通过指针),所以OrderUpdae curOrderUpdate是可以的。

  • 不,你不必(实际上你不应该)分配。原位调用构造函数是正确的:`new(&curOrderUpdate)OrderUpdate()

但是,为了确保代码的安全,必须在重新调用构造函数之前调用析构函数。所以你可以这样改变循环:

for (int i = 0; i < entries.size(); i++) {
    auto entry = entries[i];
    curOrderUpdate.~OrderUpdate();
    new (&curOrderUpdate) OrderUpdate();
    curOrderUpdate.MDEntryID = entry.get_MDEntryID().value()[0];

然而,这种低级代码最好保留给非常的特殊情况,如并集和类并集结构。特别是,正如@JamesKanze在评论中指出的那样,如果构造函数抛出(而析构函数并不是微不足道的),代码就会出现严重问题——然后你的对象会被析构函数两次。

如果您只是在OrderUpdate()中添加一个reinitialise()函数,它将在不调用析构函数和构造函数的情况下做正确的事情,那么这将是一个非常干净的设计。

在同一对象上重复调用构造函数是可疑的。正确的方法是

curOrderUpdate = OrderUpdate();