20

チャットで次の例が表示されました。

#include <iostream>
struct foo { ~foo() { std::cout << "destroying!\n"; } };
const foo& func(const foo& a, const foo&) { return a; }

int main()
{
  foo x;
  const foo& y = func(foo(), x);
  std::cout << "main\n";
}

出力

destroying!
main
destroying!

一時的なものの存続期間は、そのスコープ内のref-to-にバインドされていても、foo全体に拡張されていないことを示しているようです。mainconst

したがって、おそらく、ライフタイム延長は「1回だけ機能」します。つまり、funcの引数が初期化されるときに適用されますが、連続するバインディングを介して渡されることはありません。

私の解釈は正しいですか?もしそうなら(そして個々の段落が直接適用できる場合)、この振る舞いを定義する標準的な言い回しは何ですか?

4

4 に答える 4

9

あなたはほとんど正しいです。この動作は、実際には関数呼び出しに起因するものであり、「1回だけ機能する」というルールが原因ではありません。

関連するルールが太字で強調された、生涯拡張の「機能」の表現は次のとおりです。

[C++11: 12.2/5]: [..]参照がバインドされている一時オブジェクト、または参照がバインドされているサブオブジェクトの完全なオブジェクトである一時オブジェクトは、次の場合を除いて、参照の存続期間中存続します。

  • [..]
  • 関数呼び出し(5.2.2)の参照パラメーターへの一時的なバインドは、呼び出しを含む完全な式が完了するまで持続します。
  • [..]
于 2013-02-06T17:53:56.087 に答える
7

これは、 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299およびhttp://www.open-std.org/jtc1/sc22/の 2 つの問題レポートの対象です。 wg21/docs/cwg_active.html#1568 .

私がレポーターを務める以前の問題レポートは、参照が一時オブジェクトにバインドされているこれらすべてのケースをカバーすることを目的としていましたが、存続期間を延長することを意図していません。問題の本文の説明では、prvalues が一時的な式と混同されていることに言及しているだけです (実際には、それらが評価するものの寿命が長くなるかどうかを決定します)。しかし、lvalue と xvalue は、同様に標準でこれらと混同されています。の文脈でそれが起こる例static_castは問題番号#1568です(「一時変数」の使用は問題をさらに混乱させます)。

実際、これは:

関数呼び出し (5.2.2) の参照パラメーターへの一時的なバインドは、呼び出しを含む完全な式が完了するまで持続します。

同じ段落内の他の規則に矛盾します。一時変数は、関数呼び出しの参照パラメーターとローカル自動参照変数の両方にバインドされているためです。

于 2013-02-06T21:12:13.450 に答える
3

ここで適用されるルールは常識です。この標準は言葉遣いが不十分であり、実際にこれを保証しています。しかし、それを実装する実際的な方法はありません。

于 2013-02-06T17:58:09.900 に答える
1

おそらく私は少し遅いですが、他の回答を読んでも、この質問の解決策が何であるかが明確になりませんでした。したがって、表示されているコードを変更し、他の人のために要約したいと思いました: 答えは、y!

次のコードを実行します。

struct foo {
    int id;
    foo(int id) : id(id) { std::cout << "ctor " << id << std::endl; };
    ~foo() { std::cout << "dtor " << id << std::endl; }
};
const foo& func(const foo& a, const foo&) { return a; }

int main(int argc, char** argv) {
    foo x(1);
    const foo& y = func(foo(2), x);
    std::cout << "main " << y.id << std::endl;
    return 0;
}

私の出力は次のとおりです。

ctor 1
ctor 2
dtor 2
main 2
dtor 1

しかし、行main 2未定義の動作です。

于 2015-11-29T18:09:28.193 に答える