12

私の知る限り、戻る*thisことは overloaded を書く際の標準ですoperator=。しかし、これは右辺値を左辺値に昇格させるかもしれません!

struct Foo {
  Foo& operator=(const Foo &t) { return *this; }
};

int main() {
  const Foo &ref = Foo();
  //Foo &ref1 = Foo();  // This line won't compile.
  //But the following line compiles. Isn't it dangerous?
  //Also please note that if = is not overloaded, the synthesized operator= will NOT let it compile.
  Foo &ref2 = (Foo() = Foo());

  return 0;
}
4

2 に答える 2

7

あなたが正しい。簡単に言えば、これは合法ですが、あなたが指摘する理由から危険です。

別の(同様の)例がC ++ 11に追加され、標準の一部として、左辺値参照を返す右辺値ストリーム出力が追加されました。

template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);

したがってstd::ostream& s = std::ofstream("foo.txt") << "Oh boy";、合法ですが、ぶら下がっている参照を作成します。

C ++ 11コンパイラでは、オブジェクトが左辺値の場合にメンバー関数を制限できると思います。これにより、問題を完全に防ぐことができます。以下は、が左辺値の場合にのみ割り当てを許可する*thisため、誤って変換することを防ぎます。

struct Foo {
  Foo& operator=(const Foo &t) & { return *this; }
};
于 2012-08-19T02:09:15.203 に答える
1

最初の回答が指摘しているように、あなたがしていることは合法ですが、ぶら下がり参照になります。代入演算子をオーバーロードしなくても、ほぼ同じ結果を得ることができます。

#include <iostream>

struct Foo {
  Foo(int arg) : val(arg) { std::cout << "ctor " << val << "\n"; }
  ~Foo() { std::cout << "dtor " << val << "\n"; }
  int val;
};

int main() {
  Foo &ref = (Foo(1) = Foo(2));
  std::cout << "undefined behavior: " << ref.val << "\n";

  return 0;
}

次の出力が生成されます。

ctor 1 ctor
2
dtor 2
dtor 2
未定義の動作: 2

ご覧のとおり、一時的な forFoo(1)が構築され、その後に一時的な for が続きFoo(2)ます。ただし、参照で何かを行う前に両方のオブジェクトが破棄されるため、後続の行で未定義の動作が発生します。

于 2012-08-19T02:49:34.797 に答える