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()がクラスのメンバーまたは友人である場合は許可されます。

これが、コピーできないクラスのプライベート継承が、コピーを防止したい各クラスで「手動で」行うよりも優れている理由の1つだと思います。その場合、偶発的な抜け穴はありません。

たとえば、:を使用し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を許可したい場合もあります。

この場合、RVOが起動する限り、例は機能します。これは、本質的に非標準であるため、少し面倒です。コピーコンストラクターの定義を提供する必要がありますが、使用しないようにします。

C ++ 11では、このユースケースは、コピー操作を削除し、移動操作を定義することでサポートされます(プライベートでも)。

于 2012-04-24T08:47:51.283 に答える
0

許可されていますが、コピーコンストラクターが実装されていないため、リンクエラーが発生する場合があります。あなたがのための体を提供するならばNonCopyable( const NonCopyable&)、それはうまくいくでしょう。

于 2012-04-24T08:30:41.993 に答える
0

重要な点の1つは、実際の質問を覆い隠す可能性があります。

RVOが許可されている場合、そのような関数のユースケースは何ですか?

この関数は3つの方法で呼び出すことができ、そのうちの2つはコンパイラエラーになります。

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

返されたオブジェクトを効果的に使用することはできないため、RVOが許可されているかどうかは実際には問題ではありません。

于 2012-04-24T08:46:39.567 に答える