复制 elision/RVO 会导致从同一对象复制/移动吗?
Can copy elision/RVO cause a copy/move from the same object
假设我有一个看起来像这样的函数:
SomeObject copy_maybe(bool make_new, const SomeObject& def)
{
if (make_new)
return SomeObject();
else
return def;
}
我这样称呼它:
SomeObject obj;
obj = copy_maybe(true, obj);
如果没有复制省略,这显然总是会导致从copy_maybe
中创建的临时副本obj
。但是,使用复制省略/RVO,复制是否有可能从obj
发生到obj
?
更具体地说,在这些(或类似)条件下,在复制运算符(void operator=(SomeObject const &other)
)中,由于复制省略,this
和&other
是否可能相同?
我在 Ideone 上创建了一个测试,它返回单独的地址,但我只想确保此行为由规范定义。
但是,使用复制 elision/RVO,是否有可能从
obj
复制到obj
?
不。 Copy elison/RVO 用于初始化变量的过程。 由于您已经使用SomeObject obj;
初始化了obj
,因此不会获得任何优化。 将调用复制赋值运算符,并将为调用站点中的obj
分配函数中obj
的值。
如果你有
SomeObject obj = copy_maybe(true, obj);
那么是的,复制 elison 可以(将在 C++17 中发挥作用。
请注意,呼叫
SomeObject obj = copy_maybe(false, obj);
将使obj
处于不确定状态,因为它与
SomeObject obj = obj;
复制/移动赋值永远不能省略;省略只发生在对象的初始化时。
但是,有一种方法可以使省略应用于现有对象:
SomeObject obj;
new(&obj) auto(copy_maybe(false, obj);
C++17以一种有趣的方式定义了这一点。放置new
发生在构造新对象之前。调用new
放置称为"获取该对象的存储"。
该标准规定,当您为对象"获取存储"时,该存储中已有的任何对象的生存期都将终止(因为它们的存储正在被重用于新对象)。因此,最初声明的对象已结束其生存期。但它的析构函数不会被调用;如果您的程序依赖于在对象的生存期结束之前调用的析构函数,则您有 UB。
但这还是激怒了UB。为什么?因为obj
的一生在copy_maybe
被召唤之前就结束了。因此,copy_maybe
将获得对不再存在的对象的引用。当copy_maybe
访问对不存在对象的引用时,您将获得 UB。
同样地:
SomeObject obj = copy_maybe(false, obj);
这也激怒了UB。obj
的初始化是非空的;因此,在初始化完成之前,其生存期不会开始。这发生在copy_maybe
.但是copy_maybe
被赋予了一个尚未开始其生命周期的对象引用。那是 UB。
但是,使用复制省略/RVO,复制是否有可能从
obj
发生到obj
?
否"复制省略号/RVO"。
是的,"复制将从obj
发生到obj
",但仅作为复制分配。
建议在用户定义的副本赋值函数中检查自赋值。当你这样做时,你的代码应该可以正常工作。
SomeObject& operator=(SomeObject const& rhs)
{
// Do nothing for self assignment.
if ( this != &rhs )
{
...
}
return *this;
}
- 将包含不可复制对象的对插入到映射中
- 通用参考 l 值不复制对象
- 为什么具有 2 个参数参数的构造函数接受复制对象作为 1 个参数参数?
- 为什么从引用创建共享指针会复制对象?
- 当(且仅当)对象具有复制构造函数时,如何复制对象?
- 我的程序运行良好,可以复制对象,但是当我使用复制分配(=)时,它仍然可以正常运行.为什么不给错误
- 如何复制对象
- 如何构造不可移动不可复制对象的元组?
- 不可复制对象数组的 consexpr 初始化?
- 提升::可选与标准::不可复制对象的可选
- 如何在C++中通过引用复制对象
- 从指针复制对象
- 删除浅表的复制对象和源对象
- 使用realloc可以安全地重新分配琐碎的可复制对象的存储吗
- C 返回复制对象
- 如何将智能指针作为类属性来复制对象
- 为什么在复制对象时忽略顶级常量
- std::shared_ptr 在复制对象时导致问题
- 安全复制对象的替代方案
- 当类包含boost::container::flat_set时,复制对象时出错