2016-05-30 11 views
3

たとえば、ローカルオブジェクトを返すコンストラクタ内の関数を呼び出すクラスがあります。私はrvalue参照を使用してこのオブジェクトへのアクセスを取得しようとしています。関数でローカルに作成したオブジェクトをメモリにコピーせずに使用する方法は?

しかし、コンパイラは、参照メンバーが、建設が終了しても保持されない一時的なものに初期化されることを伝えます。

私はそれを取得しません。私は、関数のスコープ内に作成されたローカルオブジェクトは、関数のスコープ内にしか存在しないことを理解しています。スコープの終わりに達する - ローカルオブジェクトのデストラクタが呼び出されます。そして、ここで私はローカルオブジェクトでrvalue参照を初期化し、私はコンストラクタの本体にいる間、私はそれにアクセスできます。

誰かが説明することができますか、ここで何が起こっていますか?そして、ローカルオブジェクトを返し、それをメモリ内で動かすことなく、任意のクラスメンバーとして使用する方法がありますか?

+1

"私はコンストラクタのボディにいるうちに" 'C(f())'は 'c'tor'ボディにありません。初期化リストにあります。 – sameerkn

+1

参照先の参照先は何ですか?誰がメモリを所有し、所有者はそのメモリをどのように処分しますか? @ sameerkn、 –

+0

?私はコンストラクタ本体でこのオブジェクトにアクセスできると書いています。明らかに、私は初期化リストでこれを初期化します。 –

答えて

5

&&Cから削除する必要があります。

コードは想像以上に高価ではありません。fの戻り値はcopy elisionです。したがって、コンパイラはCのメモリ空間にただ一つのBigObjectを直接構築することができます。コンパイラがこれを実行しなくても、それは移動コンテキストであるため、最悪のシナリオではオブジェクトが移動します。

あなたのオブジェクトが何らかの形でコピーできますが、移動できない場合は、コピーelisionに頼らざるを得ませんが、そのようなオブジェクトの有効なユースケースを想像するのは難しいです。標準からそれを引用する

1


12.2.5項
参照が 一時的にバインドされているときに、第2のコンテキストがあります。参照がバインドされている一時的なもの、または 参照がバインドされているサブオブジェクトの完全なオブジェクトである 一時的なもの: - コンストラクタの ctorの参照メンバへの一時的なバインド初期化子(12.6.2)は、コンストラクタが終了するまで存続します。

したがって、C(f())では、コンストラクタが終了するまでCが一時的にバインドされ、その後はUBのようなものになります。コンパイラが警告を発したことに感謝しています:)。

とにかく、このようなアクロバットを行う必要はありませんが、一時的なものからいつでも「C」に移動できます。この場合、コンパイラは

class BigObject 
{ 
public: 
    BigObject() {std::cout << "Cons" << std::endl;} 
    BigObject(const BigObject& other) {std::cout << "Copy Cons" << std::endl;} 
    BigObject(BigObject&& other) {std::cout << "Move Cons" << std::endl;} 
}; 

BigObject f() 
{ 
    return BigObject(); 
} 

class MyClass 
{ 
public: 
    BigObject C; 

    MyClass() : C(f()) 
    { 
    }; 

}; 

非常によくちょうど標的部位に一度「BigObject」を構築することによって可能な限り効率的なように、コードを作るコピーをElideのことができます。

ので、この特定のケースにはそれがは可能性があり、あなたのオブジェクトがすべてで移動したり、コピーされません可能。おそらくそれはあなたの最後の質問に答えます。

関連する問題