3

一時オブジェクトを変更して引数として渡すことはできますか?

struct Foo {    
   Foo& ref() { return *this; }
   Foo& operator--() { /*do something*/; return *this; }
   // another members
};
Foo getfoo() { return Foo(); } // return Foo() for example or something else
void func_val(Foo x) {}
void func_ref(const Foo & x) {}

int main() {
   func_val(--getfoo());     // #1 OK?
   func_ref(getfoo());       // #2 OK?
   func_ref(getfoo().ref()); // #3 OK?
   // the following line is a real example 
   //    using --vector.end() instead of --getfoo()
   func_ref(--getfoo());     // #4 OK? 

   const Foo & xref = --getfoo(); //  Does const extend the lifetime ?
   func_ref(xref);     // #5 OK? 
   func_val(xref);     // #6 OK? 

}

一時オブジェクトを const 参照に割り当てると、この一時オブジェクトの寿命が延びることが知られています。コードの 4 行目と 5 行目はどうでしょうか。関数 func_ref で参照 x が常に有効であるというのは本当ですか? 問題は、operator-- が何らかの参照を返し、コンパイラーがこの参照と作成した一時オブジェクトとの関係を認識しないことです。

4

2 に答える 2

4

とにかく、テンポラリーは、それらが作成された完全な式の存続期間中、常に存続します。したがって、式 statement func_val(--getfoo());では、式によって返されるテンポラリの有効期間をgetfoo()延長する必要はありません。func_val()afterが戻るまで、ステートメントは終了しません。

于 2009-10-15T11:21:42.663 に答える
3
func_val(--getfoo());     // #1 OK?

うんいいよ。はoperator--メンバー関数であり、呼び出されて自分自身 (および自分自身を参照する左辺値) を返します。次に、オブジェクトが のパラメータにコピーされますfunc_valgetfoo()によって作成された一時は以前に参照にバインドされていたため、戻り値の最適化は適用できないことに注意してください。

func_ref(getfoo());       // #2 OK?

うんいいよ。この呼び出しgetfoo()は、const 参照にバインドされた一時を返します。コピー コンストラクターが必要ですが、その呼び出しは実装によって最適化される場合があります。func_ref一時的なものは、への呼び出しを含む完全な式(ここでは式ステートメント全体)の終わりまで持続します。

func_ref(getfoo().ref());

うんいいよ。const 参照を一時的なものではなく、オブジェクト自体を表す左辺値にバインドするため、コピー コンストラクターは必要ありません。

// the following line is a real example 
//    using --vector.end() instead of --getfoo()

それは働く必要はありません。(許可)をvector.end()返す状況を考えてみてください。T*非クラス型の右辺値を変更することは許可されていないため、その場合、これは不適切な形式になります。

func_ref(--getfoo()); 

うんいいよ。引数は のように評価されます#1が、結果の左辺値は直接渡され、const 参照はそれにバインドされます。この意味で#3は、(デクリメントの副作用を除いて) と同じです。

const Foo & xref = --getfoo();

標準の文言は完全には明確ではありません。まだ参照にバインドされていないオブジェクトの有効期間のみを延長することを確実に意図しています。しかし、私たちの場合、--getfoo()以前に参照にバインドされた一時オブジェクトを参照する左辺値を生成します。委員会に欠陥レポートを提出する価値があるかもしれません (一時オブジェクトがまだ参照にバインドされていないことを要求する文言を見逃している可能性もあります)。

いずれにせよ、意図された動作はgetfoo()、初期化の最後に結果として生じる一時的なものを破棄することxrefであるためxref、ダングリング リファレンスになります。

問題は、operator-- が何らかの参照を返し、コンパイラーがこの参照と作成した一時オブジェクトとの関係を認識しないことです。

正確に(ただし、狂う初期化にのみ適用されますxref。他のすべての場合では、意図した動作(または必要と思われる動作)が達成されます)。

于 2009-10-15T11:40:05.603 に答える