10

假设我有一个类,其中复制构造函数是私有的且未实现(使对象不可复制)

class NonCopyable {
// whatever
 private:
    NonCopyable( const NonCopyable&);
    void operator=(const NonCopyable&);
 };

现在在同一个类的一些成员函数中,我编写了返回该类对象的代码:

NonCopyable NonCopyable::Something()
{
    return NonCopyable();
}

这是 RVO 可以介入的情况。

RVO 仍然要求可以访问复制构造函数。由于对复制构造函数的可能调用是在同一个类成员函数中完成的,因此复制构造函数是可访问的。因此,尽管意图是禁止使用复制构造函数,但从技术上讲,RVO 是可能的。

在这种情况下是否允许 RVO?

4

4 回答 4

6

是的,在这种情况下允许 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
}
于 2012-04-24T08:30:41.790 回答
5

你的例子很有趣。

这是典型的 C++03 声明。

class NC {
public:
    NC NC::Something() {
        return NC();
    }

private:
    NC(NC const&);
    NC& operator=(NC const&);
};

在这里,如前所述,即使我们在语义上希望避免复制,RVO 也可能会发挥作用。

在 C++03 中,解决方案是委托:

class NC: boost::noncopyable {
public:
    NC NC::Something() { // Error: no copy constructor
        return NC();
    }
};

在 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;
};

但有时,我们想阻止复制,却想允许Builder(就像在Pattern 中一样)。

在这种情况下,只要 RVO 启动,您的示例就可以工作,这有点烦人,因为它本质上是非标准的。应提供复制构造函数的定义,但您不希望使用它。

在 C++11 中,通过删除复制操作和定义移动操作(甚至是私有的)来支持此用例。

于 2012-04-24T08:47:51.283 回答
0

One important point may overshadow the actual question.

What is the use case of such function if RVO is allowed ?

This function can be called in 3 ways and 2 of them will be a compiler error:

NonCopyable obj;
NonCopyable obj2 = obj; // 1 --> error
NonCopyable &r = obj;   // 2 --> error
const NonCopyable &rc = obj; // 3 --> ok, but dangerous (may lead to UB)

One can't use the returned object effectively, so it really doesn't matter if the RVO is allowed or not.

于 2012-04-24T08:46:39.567 回答
0

这是允许的,但您可能会收到链接错误,因为未实现复制构造函数。如果您为 提供一个主体NonCopyable( const NonCopyable&),它将起作用。

于 2012-04-24T08:30:41.993 回答