2017-06-27 3 views
4

のは、次のサンプルを検討してみましょう:RVOが全くとどのような方法で存在禁じられたりされていない仮定の下C++標準:RVOを使用せずに参照を初期化するためにコピーで返す:コピーはありますか?

struct big_type {}; 

// Return by copy 
auto factory() { return big_type{}; } 

void any_scope_or_function() { 
    big_type&& lifetime_extended = factory(); 
} 

を、またはbig_type()コピーすることができますでしょうか?または、参考文献はreturnの声明の中で一時的に構成されたものに直接拘束されるでしょうか?

any_scope_or_functionが終了すると、big_typeデストラクタが1回だけ呼び出されることを確認します。

私はC++ 14を使用していますが、標準のバージョン間で動作が変更されている場合があります。一時的なbig_typeを作成しようとしている

auto factory() { return big_type{}; } 

big_type{}で、その後何のRVO /コピーelisonがないと仮定すると、

+0

@ NathanOliverコンパイラスイッチを削除するのを忘れてしまった。腐った。 –

+0

さらに、私はC++ 17を使うことができません。 C++ 14までです。 –

+1

@ Peregring-lkしかし、レコード用です。これは、C++で変更されました.17では、ここではコピーの削除はもう必要ありません。 –

答えて

8

。このオブジェクトは、その後にコピーされます。関数が返すオブジェクトを初期化します。これは、関数内で作ったオブジェクトが構築され、破壊されることを意味します。機能の寿命を延長します

big_type&& lifetime_extended = factory(); 

右辺値参照して

ので、我々は、全デフォルトコンストラクタ呼び出し、コピー/移動のコンストラクタ呼び出し、および2回のデストラクタの呼び出しで表示されます戻ります。今

、我々は、我々はもはや工場でオブジェクトを作成している

big_type factory() { return {}; } 

auto factory() { return big_type{}; } 

を変更しない場合。リターン・オブジェクトが直接{}が総デフォルトコンストラクタ呼び出しとデストラクタの呼び出し

3

または参照を直接return文の中に一時的に構築 にバインドされるのですか?で私たちを与えることで初期化されますか

いいえ、そうではありません。それはまさに(N)RVOが約/ forであり、明示的にそれを望んでいないものです。

ただし、実際にはコピーではないbig_typeのムーブコンストラクタを使用して試行されます。違反します:any_scope_or_function終了時にbig_typeデストラクターが一度だけ呼び出されます。が2回呼び出されるためです。

GCC/Clangは、後で参照するために使用できる(N)RVOを無効にする素晴らしいコンパイルスイッチを持っています:-fno-elide-constructors今のところ、hereは、そのオプションがオンになっているテストで、デストラクタを2回呼び出すと表示されます。

関連する問題