有没有办法在 C++ 中进行就地成员构造(无需复制和破坏对象)?
Is there a way to do in-place member construction in C++ (without copying and destructing an object)?
所以,我终于在我的软件中找到了一个奇怪的崩溃,这是因为我之前 运行 遇到的一个问题:
m_member = Foo(var1, var2)
我意识到是使用 var1 和 var2 执行 Foo 的构造,通过复制分配将 Foo 的这个实例分配给 m_member,然后删除原始实例。有没有办法避免这种行为并有类似于:
m_member(var1, var2);
我知道这可以在初始化列表中完成,但不幸的是,我正在为一个已经构造的对象修改这个成员。有什么想法吗?
strange crash ... which is happening because ... Which I've realized is performing a construction of Foo using var1 and var2, assigning this instantiation of Foo to m_member via a copy construction, and then is deleting the original instance.
如果这样做导致崩溃,那么成员 class 的设计就被破坏了。可能(但我不能确定)由于未能在赋值运算符中强制执行 class 不变性,这对于防止析构函数具有未定义的行为是必要的。
Is there a way to avoid this behavior
如果您需要分配成员,那么您必须分配成员。如果我的怀疑是正确的,您可以通过修复赋值运算符来修复程序。
如果您不需要分配成员,则可以通过不分配来避免此行为。但无论如何都要修复赋值运算符。
因为你没有展示 class,我不知道它为什么坏了,但很可能你应该查看析构函数和赋值运算符并考虑可能导致它们的情况未定义的行为。
Is there a way to avoid this behavior and have something akin to:
m_member(var1, var2);
只有在初始化成员时才有可能。
这里有几个选项,假设您的问题来自复制分配:
改用指针类型
将 m_member
更改为 Foo*
,或者更好的 std::unique_ptr<Foo>
,以更好地匹配之前的行为,然后执行:
m_member = std::make_unique<Foo>(var1, var2);
没有副本,仍然会在你的范围结束时被销毁,并且根据你的问题描述,这可能意味着你的“Foo”资源将作为指针得到更有效的管理。
你也可以...
定义一个move-assignment运算符
现在这意味着您必须定义 the big 5,但是定义移动赋值运算符可以避免复制。
Foo& operator=(const Foo& other)
{
// Copy the attributes you need to copy
var1_ = other.var1_;
var2_ = other.var2_;
return *this;
}
这将有效修改 Foo
in-place.
修复 copy-assignment?
现在这真的回答了你的问题,但毫无戒心的开发人员当然希望这不会崩溃,而且这个问题很可能会出现在其他地方,因为 copy-assignment 在写作时经常出现代码和标准算法。但是有多种原因可能无法做到这一点,所以我让你来判断!
所以,我终于在我的软件中找到了一个奇怪的崩溃,这是因为我之前 运行 遇到的一个问题:
m_member = Foo(var1, var2)
我意识到是使用 var1 和 var2 执行 Foo 的构造,通过复制分配将 Foo 的这个实例分配给 m_member,然后删除原始实例。有没有办法避免这种行为并有类似于:
m_member(var1, var2);
我知道这可以在初始化列表中完成,但不幸的是,我正在为一个已经构造的对象修改这个成员。有什么想法吗?
strange crash ... which is happening because ... Which I've realized is performing a construction of Foo using var1 and var2, assigning this instantiation of Foo to m_member via a copy construction, and then is deleting the original instance.
如果这样做导致崩溃,那么成员 class 的设计就被破坏了。可能(但我不能确定)由于未能在赋值运算符中强制执行 class 不变性,这对于防止析构函数具有未定义的行为是必要的。
Is there a way to avoid this behavior
如果您需要分配成员,那么您必须分配成员。如果我的怀疑是正确的,您可以通过修复赋值运算符来修复程序。
如果您不需要分配成员,则可以通过不分配来避免此行为。但无论如何都要修复赋值运算符。
因为你没有展示 class,我不知道它为什么坏了,但很可能你应该查看析构函数和赋值运算符并考虑可能导致它们的情况未定义的行为。
Is there a way to avoid this behavior and have something akin to:
m_member(var1, var2);
只有在初始化成员时才有可能。
这里有几个选项,假设您的问题来自复制分配:
改用指针类型
将 m_member
更改为 Foo*
,或者更好的 std::unique_ptr<Foo>
,以更好地匹配之前的行为,然后执行:
m_member = std::make_unique<Foo>(var1, var2);
没有副本,仍然会在你的范围结束时被销毁,并且根据你的问题描述,这可能意味着你的“Foo”资源将作为指针得到更有效的管理。
你也可以...
定义一个move-assignment运算符
现在这意味着您必须定义 the big 5,但是定义移动赋值运算符可以避免复制。
Foo& operator=(const Foo& other)
{
// Copy the attributes you need to copy
var1_ = other.var1_;
var2_ = other.var2_;
return *this;
}
这将有效修改 Foo
in-place.
修复 copy-assignment?
现在这真的回答了你的问题,但毫无戒心的开发人员当然希望这不会崩溃,而且这个问题很可能会出现在其他地方,因为 copy-assignment 在写作时经常出现代码和标准算法。但是有多种原因可能无法做到这一点,所以我让你来判断!