【发布时间】:2018-03-09 14:02:59
【问题描述】:
Stack Overflow 上有很多关于 std::move 和复制省略的交互的帖子,例如
What are copy elision and return value optimization?
How to be confident of copy elision / return-value optimization
c++11 Return value optimization or move?
但是,所有这些线程似乎都没有回答这个问题,即是否可以依靠编译器进行必要的优化。
如果在最坏的情况下我们的性能略有下降,这不是问题,但如果由于可能重复的析构函数调用而与正确性冲突,则可能是致命的。
我有以下情况:
class ObjectContainer {
Object* obj;
public:
ObjectContainer(Object* o): obj(o) {}
~ObjectContainer() {
if (obj) delete obj;
}
ObjectContainer(ObjectContainer&& other): obj(other.obj) {
other.obj = nullptr;
}
};
ObjectContainer create_container() {
return ObjectContainer(new Object());
}
那里会发生什么?这能保证工作吗?或者是否存在代码无法编译的情况,或者更糟糕的是,析构函数在同一个对象上被调用两次?
据我了解,如果我声明了移动构造函数,编译器不会生成默认的复制构造函数。我必须指定一个复制构造函数吗?如果我这样做会怎样?还是应该在 return 语句中使用 std::move?
我将像这样调用上面的方法:
void do_stuff() {
do_some_other_stuff(create_container());
}
void do_some_other_stuff(ObjectContainer const& oc) {
...
}
【问题讨论】:
-
我相信很多答案都提到复制省略在 C++17 中是必需的,并且之前只允许使用。
-
您违反了Rule of zero / 5,这将导致许多其他问题。如果你修复它,它也会使这种情况正常运行,而不会出现复制省略。
-
感谢您的回答。在这种情况下,在不为 obj 添加引用计数器的情况下引入复制构造函数在语义上真的没有意义,是吗?我不知道 C++17 需要复制省略(我不记得在答案中的任何地方看到过该声明)。所以这意味着在 C++17 中,即使没有移动构造函数,这也很好?但是,我的代码也应该在 C++11 中工作。
标签: c++11 copy-elision return-value-optimization stdmove