4

このコードはコンパイルされますが、私は C++11 の勉強を始めたばかりで、舞台裏で何が起こっているのか理解できません。

void func(int&& var)
{
    int var2(var);
}

void main()
{

    int var1 = 22;
    func(move(var1));
}

私の推測: move(var1) は var1 の r 値 (おそらくそのデータ) を返し、func 関数は var1 の r 値で var2 を初期化しています。しかし、なぜ func 呼び出し後も var1 がまだ有効なのでしょうか? 一時値が var2 に再割り当てされているため、無効な値を持つべきではありませんか?

4

5 に答える 5

2

var1は左辺値です。適用するstd::move(var1)と、同じオブジェクトを参照する右辺値が得られます。int&&次に、この右辺値を呼び出された にバインドしvarます。

varも左辺値です。これは、名前付き変数である式は左辺値であるためです (その型が右辺値参照であっても)。次にvar2、 の値で初期化しますvar

var1つまり、値を からにコピーしただけですvar2。何も動かされていません。実際、 のような基本型から移動することさえできませんint。一時的なものから初期化または割り当てを試みると、intその値がコピーされるだけで、何も移動されません。

移動コンストラクターと代入演算子を持つ型を使用しTていたとしても、コードは何も移動しません。これは、参照以外の初期化を行うのは lineint var2(var);だけだからですが、ここvarには左辺値があります。つまり、代わりにコピー コンストラクターが使用されます。

var1からに移動する最も簡単な方法は、次のvar2ようにすることです。

void func(T var)
{
    T var2(move(var));
}

void main()
{

    T var1(22);
    func(move(var1));
}

これは から create に移動しvar1var次に から create に移動varしますvar2

右辺値参照に戻すことを除いて、ほぼ同じ方法でこれを行うことができvarますが、お勧めしません。渡される右辺値が内部移動によって無効になることを文書化する必要があります。

于 2013-04-02T12:12:59.097 に答える
1

move(var1) は、var1 の右辺値 (おそらくそのデータ) を返します。

いいえ、move(var1)を参照して右辺値参照を返しますvar1

func 関数は var1 の r 値で var2 を初期化しています

funcにコピーvar1var2ます。移動コンストラクタを持つ型の場合var1、移動コンストラクタが呼び出されて initialize になりますvar2。そうではありません。

しかし、なぜ func 呼び出し後も var1 がまだ有効なのでしょうか?

をコピーしintても無効にならないためです。

無効な値を持つべきではありませんか?

の特別な「無効な値」はありませんint。初期化されていないオブジェクトを使用すると動作が未定義になりますが、このオブジェクトは初期化されていません。

于 2013-04-02T12:17:54.497 に答える
1

他の人が述べたように、あなたの例では、基本的にコピーを呼び出すプリミティブ型を使用しています。ただし、 を使用して、移動が発生する可能性がある例を作成しましたstd::string。その内臓は下から動かすことができ、この例でそれが起こっていることがわかります.

#include<iostream>
#include<string>
#include<utility>

void func(std::string&& var)
{
    // var is an lvalue, so call std::move on it to make it an rvalue to invoke move ctor
    std::string var2(std::move(var));
    std::cout << "var2: " << var2 << std::endl;
}

int main()
{

    std::string var1 = "Tony";
    std::cout << "before call: " << var1 << std::endl;
    func(std::move(var1));
    std::cout << "after call: "  << var1 << std::endl;
}

出力:

before call: Tony
var2: Tony
after call: 

var1実際に移動されており、データが含まれていないことがわかりますが、標準では未指定の状態であり、再利用可能です。

実際の例

于 2013-04-02T12:18:14.267 に答える