3

このコードはコンパイルされません:

class C {};

void foo (C& c) {}

C bar() { return C(); }

int main()              
{
  foo(bar());
}               

行のコンパイル エラー (GCC 4.1.2) foo(bar()):

タイプ 'C' のテンポラリからのタイプ 'C&' の非 const 参照の無効な初期化

Asはオブジェクトをbar()返し、mutableコンパイルする必要があります...
なぜ C++ は上記のコードを許可しないのですか?


編集:すべての回答からのすべての良いアイデアの下に回答をまとめました;-)

4

8 に答える 8

13

ここで適用されるルールは、一時オブジェクトへの非 const 参照を作成できないことです。コードfooとして宣言されていれば問題ありません。foo(const C&)

ただし、一時オブジェクト自体は const ではありません。その上で非 const メンバー関数を呼び出すことができますbar().non_const_member_function()

C++11 では、右辺値参照を取るように foo を記述できます。その場合、呼び出しは問題ありません。

void foo(C&&);
foo(bar());  // okay
于 2012-11-14T19:13:46.553 に答える
8

によって返される値bar一時的な値であるためです。その存在は一時的なものであるため、それへのポインターまたは参照を使用することはできません。

ただし、2 番目の変更のように、その一時オブジェクトのコピーを保存すると、一時オブジェクトへの参照を に渡すのではなくfoo、実際の有形オブジェクトへの参照を渡すことになります。そして最初のケースでは、定数オブジェクトへの参照に変更すると、コンパイラは一時オブジェクトが十分長く存在することを確認します (C++ 仕様に従って)。

于 2012-11-14T19:12:27.633 に答える
3

変更可能な (左辺値) 参照は、一時的な値にバインドされません。ただし、const-references一時的な値にバインドします。value によって返されるオブジェクトが const であるかどうかとは関係ありません。式が一時的なものかどうかの問題です。

たとえば、次有効です。

struct C { void i_am_non_const() {} };

int main()
{
    bar().i_am_non_const();
}
于 2012-11-14T19:13:01.130 に答える
3

問題は の宣言ではなく、 の宣言にbarありfooます。foo非参照を取り、const一時オブジェクトは参照にのみバインドできconstます (これにより、バインド先の参照の寿命と一致するように一時オブジェクトの寿命が延長されます)。

const参照をテンポラリにバインドできるようにすることはあまり意味がありません。非const参照は、それにバインドされているオブジェクトを変更することを意味します。一時的なものを変更しても、その有効期間は限られているため、何の役にも立ちません。また、変更は範囲外になるとすぐに失われます。

于 2012-11-14T19:13:16.900 に答える
1

const ではありませんが、一時的なrvalueです。そのため、非 const左辺値参照にはバインドできません。

const または右辺値参照にバインドでき、その上でメンバー関数 (const かどうかに関係なく) を呼び出すことができます。

class C { void f(); };

void foo_const(C const &);
void foo_rvalue(C &&);

foo_const( bar() );  // OK
foo_rvalue( bar() ); // OK
bar().f();           // OK
于 2012-11-14T19:15:35.963 に答える
1

デザイン選びです。ここでは本質的に不可能なことは何もありません。単なるデザインの選択。

C++11 では、優れた代替手段でもある 3 番目の代替手段があります。

void foo(C && c) {} 

つまり、右辺値参照を使用します。

于 2012-11-14T19:13:53.757 に答える
0

本当の難しい真実は、一時的な値への参照を取得することは意味がないということです。

参照によってオブジェクトを渡すことの大きなポイントは、オブジェクトの状態を変更できることです。ただし、一時的な場合は、その性質上、変更を確認するためにコードの後半で別の参照を取得する方法がないため、変更できることは特に役に立ちません。

ただし、参照がある場合、これは多少異なりconstます。参照からのみ読み取るのでconst、そこで一時的なものを使用できることは完全に理にかなっています。これが、コンパイラがその周りを「ハッキング」し、参照に「変換」したい一時的なアドレスに、より永続的なアドレスを与える理由ですconst

constしたがって、一時的な値への非参照を取得することはできないという規則があります。(これはC ++ 11でわずかに変更されました。この場合、この正確な目的に役立つ新しいタイプの参照がありますが、メソッドはそれらを特別な方法で処理することが期待されます。)

于 2012-11-14T19:15:05.633 に答える
0

回答ありがとうございます :-)
ここにあなたの良いアイデアを集めます ;-)

答え

値引きは行っておりません const。たとえば、return by valueの非 const メンバー関数を呼び出すことができます。

class C { 
  public:
    int x;
    void set (int n) { x = n; }  // non-const function
};

C bar()  { return C(); }

int main ()
{
    bar.set(5); // OK
}

ただし、C++ では一時オブジェクトへの非 const 参照は許可されません。ただし、C++11 では、一時オブジェクトへの
非 const右辺値参照が許可されます。;-)

説明

class C {};

void foo (C& c) {}

C bar()  { return C(); }
//bar() returns a temporary object
//temporary objects cannot be non-const referenced

int main()
{
  //foo() wants a mutable reference (i.e. non-const)
  foo( bar() ); // => compilation error     
}                 

3 つの修正

  1. 変更foo宣言

      void foo (const C& c) {}
    
  2. 別のオブジェクトを使用する

      int main()              
      {
        C c;
        foo( c = bar() );
      }
    
  3. C++11右辺値参照を使用する

      void foo(C && c) {}
    

さらに

一時オブジェクトが const であることを確認するには、上記のソース コードは同じ理由で失敗します。

class C {};

void foo(C& c) {}

int main()                
{
  foo( C() );
}            
于 2012-11-14T19:23:04.610 に答える