2017-02-28 8 views
3
#include <vector> 

using namespace std; 

void f(const vector<int>&) {} 
void f(vector<int>&&) {} 

int main() 
{ 
    { 
     vector<int> coll; 

     // 
     // coll is dying, so, 
     // "f(coll)" will call "f(const vector<int>&)" or 
     // "f(vector<int>&&)" as per C++11? 
     // 
     f(coll); 
    } 
} 

上記のコードでは、collが死んでいます。だから、f(coll)f(const vector<int>&)またはf(vector<int>&&)をC++ 11と呼ぶでしょうか?C++ 11は、死にかけているオブジェクトが引数としてコピーされるのではなく移動されることを保証しますか?

+9

いいえ;この場合、 'f(const std :: vector &')を呼び出します。あなたが作っている呼び出しでは、 'coll'は名前付きの左辺値です。 'coll'が次の行のスコープから外れるという事実は無関係です。右辺の 'foo'を呼び出す場合は、' f(std :: move(coll)) 'を使うべきです。 –

+0

あなたは何を意味していますか?コール後に破棄されます。あなたは 'foo(vector ());' –

+1

'coll'のようなものを意味していました。ブレース内では完全に健全です:-)したがって、右辺値を取得したい場合は、明示的な 'std :: move(coll)'が必要です – AndyG

答えて

5

f(coll)f(const vector<int>&)の代わりにf(vector<int>&&)と指定すると、間違った機能のオーバーロードが選択されるため、標準違反となります。

コールがどこにあるか、およびコール後にcollを使用して後続のステートメントがあるかどうかによって、コールの解像度が異なる場合は、むしろ混乱します。

特別な治療が唯一return valuesに与えられる:

expressionは左辺値表現とエリジオンが満たされている、または満たされることになるコピーのための条件は、その後、その式名を除いて、関数のパラメータである場合戻り値の初期化に使用するコンストラクタを選択するためのオーバーロードの解決は、最初にexpressionがrvalue式であるかのように(つまり、moveコンストラクタまたはconstを参照するコピーコンストラクタを選択することができます)、適切な変換がない場合使用可能な場合、lvalue式で2回目のオーバーロード解像度が実行されます(したがって、 yコンストラクタは非constを参照します)。

+5

これを追加するだけです。この場合、コンパイラは 'foo'のrvalueバージョンを呼び出します(' coll'は間違いなく次の行のスコープから外れています)。これが許されれば、誰かが次の行に 'coll'を使った文を追加すると、プログラムの振る舞いが変わるからです。ほとんどの人には混乱するだろう。 –

関連する問題