sha*_*oth 9 c++ copy-constructor rvo
假设我有一个类,其中复制构造函数是私有的而未实现(使对象不可复制)
class NonCopyable {
// whatever
private:
NonCopyable( const NonCopyable&);
void operator=(const NonCopyable&);
};
Run Code Online (Sandbox Code Playgroud)
现在在同一个类的一些成员函数中,我编写了返回该类对象的代码:
NonCopyable NonCopyable::Something()
{
return NonCopyable();
}
Run Code Online (Sandbox Code Playgroud)
这是RVO可以参与的情况.
RVO仍然要求可以访问复制构造函数.由于可以从同一个类成员函数中对复制构造函数进行可能的调用,因此可以访问复制构造函数.因此技术上RVO是可能的,尽管意图是禁止使用复制构造函数.
在这种情况下是否允许RVO?
是的,在这种情况下将允许RVO - 至少如果呼叫者Something()是集体成员或朋友.
我认为这就是为什么非可复制类的私有继承比你想要防止复制的每个类中"手动"更好的原因之一.在这种情况下,没有意外的漏洞.
例如,使用boost::noncopyable:
class NonCopyable : private boost::noncopyable {
public:
NonCopyable() {};
NonCopyable Something();
};
NonCopyable NonCopyable::Something()
{
return NonCopyable(); // causes compile time error, not link time error
}
Run Code Online (Sandbox Code Playgroud)
你的例子很有趣。
这是典型的 C++03 声明。
class NC {
public:
NC NC::Something() {
return NC();
}
private:
NC(NC const&);
NC& operator=(NC const&);
};
Run Code Online (Sandbox Code Playgroud)
在这里,如上所述,即使我们在语义上想要避免复制,RVO 也可能会起作用。
在 C++03 中,解决方案是委托:
class NC: boost::noncopyable {
public:
NC NC::Something() { // Error: no copy constructor
return NC();
}
};
Run Code Online (Sandbox Code Playgroud)
在 C++11 中,我们可以选择使用delete关键字:
class NC {
public:
NC NC::Something() { // Error: deleted copy constructor
return NC();
}
private:
NC(NC const&) = delete;
NC& operator=(NC const&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
但有时,我们想阻止复制,但又想允许Builder(如在 Pattern 中)。
在这种情况下,只要 RVO 启动,您的示例就可以工作,这有点烦人,因为它本质上是非标准的。应提供复制构造函数的定义,但您不希望使用它。
在 C++11 中,通过删除复制操作和定义移动操作(甚至是私有的)来支持这个用例。