2015-09-03 1 views
6

operator+ & coは、右辺値に対してthisで操作できます。すなわち、クラスC与えられ、それがこれを行うことが可能です:臨界を防ぐために演算子をref-qualifierでオーバーロードすることは妥当ですか?

class C { 
    // ... 
    C operator-(const C& rhs) const & { 
     C result = *this; 
     result -= rhs; 
     return result; 
    } 
    C&& operator-(const C& rhs) && { 
     *this -= rhs; 
     return std::move(*this); 
    } 
}; 

これは、単にその場で一時的な値を変更することで、コピーを防止するであろう。

これは私の予想どおりに動作しますか?これは妥当な最適化ですか、コンパイラは同じように高速なコードを作成しますか?

+0

最初のバージョンでは、すでにellisionコピーを取得できます。だから、私は2番目のものが必要であるかどうか分からない。(それはまったく動作すれば、お尻を噛むように感じるが、間違っている可能性がある) – Borgleader

+0

ええ、コピーエリージョンが同様の性能をもたらすかもしれないと感じている。 ..しかし、私のバージョンでは、私のお尻が私のお尻をどうやって噛むのかは分かりません。 (私は確信していないので、質問です。) –

+0

オブジェクトの生涯の問題です。 'C && c = C() - some_C;'と 'c'はぶら下がっています。 –

答えて

5

のは我々だけstd::stringをラップし、operator+の簡易版行いましょう。それと

struct C { 
    std::string val; 

    C&& operator+(const C& rhs) && { 
     val += rhs.val; 
     return std::move(*this); 
    } 

    std::string::iterator begin() { return val.begin(); } 
    std::string::iterator end() { return val.end(); } 
}; 

を、これは正常に動作します:

for (char c : C{"hello"}) { .. } 

範囲-のための式は、の寿命を延長します一時的なので、私たちは大丈夫です。しかし、このことを考慮してください。

for (char c : C{"hello"} + C{"goodbye"}) { .. } 

は、我々は効果的に持っている:

auto&& __range = C{"hello"}.operator+(C{"goodbye"}); 

をここで、私たちはリファレンスに一時的に結合していません。私たちは参照をバインドしています。オブジェクトはその存続期間が延長されません。なぜなら、オブジェクトではないからです。だから私たちには、参照が不明で、未定義の動作があります。これは、これが動作するように期待するユーザーに非常に驚くべきことのようになります。

for (char c : std::string{"hello"} + std::string{"goodbye"}) { .. } 

あなたが値を返す必要があるだろう。(今は一時的な拡張子を持っているように)この問題を解決

C operator+(const C& rhs) && { 
    val += rhs.val; 
    return std::move(*this); 
} 

を、あなたのオブジェクトを動かすことがそれらをコピーするより安ければ、これは勝利です。

関連する問題