5

私が知っていること

一時オブジェクトの const 参照を返すことは問題ないことを知っています! (この例のように:)

class A {
public:
  virtual const A& clone () { return (A()); }
  virtual std::string name() const { return ("A"); }
};

一時オブジェクトを返し、const 参照にバインドする

しかし!

私がそれをしたいのなら、それはまだ正しいです:

class B : public A {
public:
  virtual const A& clone () { return (B()); }
  virtual std::string name() const { return ("B"); }
};

はいと思いますが、実行時には、返されたオブジェクトはまだ A オブジェクトと見なされます (この例のように:)

main.cpp

#include <iostream>
#include <string>
int main() {
  B bb;
  A* aa = &bb;

  std::cout << aa->clone().name() << std::endl;
}

出力

valgrind ./a.out
==14106== Use of uninitialised value of size 8
==14106==    at 0x401BF9: main (main.cpp:8)
==14106==  Uninitialised value was created by a stack allocation
==14106==    at 0x401BF2: main (main.cpp:8)
B

それはB..イェーイ..しかし、この警告は非常に恐ろしいです....

編集

あなたのおかげで、私は自分のエラーを見ていることを知っています...しかし、それについて他のことを知りたいです...

これが実行されると、スタック内で正確に何が起こっているのでしょうか?

4

1 に答える 1

11

参照を一時オブジェクトにバインドすると、一時オブジェクトの有効期間が延長されます...そうでない場合を除きます。§12.2 [class.temporary]/p5、強調を追加:

参照がバインドされている一時オブジェクト、または参照がバインドされているサブオブジェクトの完全なオブジェクトである一時オブジェクトは、次の例外を除き、参照の存続期間中持続します。

  • コンストラクターの ctor -initializer (12.6.2)の参照メンバーへの一時的なバインドは、コンストラクターが終了するまで持続します。
  • 関数呼び出し (5.2.2) の参照パラメーターへの一時的なバインドは 、呼び出しを含む完全な式が完了するまで持続します。
  • 関数 return ステートメント (6.6.3) の戻り値に一時的にバインドされているものの有効期間は延長されません。一時的なものは、return ステートメントの完全な式の最後で破棄されます。
  • new-initializer (5.3.4) の参照への一時的なバインドは、 new-initializer を含む完全な式が完了するまで持続します

リンクした質問のケース ( std::string foo(); const std::string & s = foo();) は問題ありません。によって返されるテンポラリの有効期間は、の有効期間が終了するfoo()まで延長されます。sコードでは、テンポラリは戻り値にバインドされ、上記の 3 番目の箇条書きに従って、その有効期間は延長されず、関数はダングリング リファレンスを返します。

通常、clone()関数はヒープに割り当てられたコピーへのポインターを返す必要があります。

于 2014-10-09T16:33:21.147 に答える