6

新しく追加された右辺値参照( vs2012 express )を試していました。

何だか分かりませんとも。以下のコードを考えると(そのほとんどは std::forward が説明されているc++標準から取られています)。

struct A
{
    A(int& i, const float& j):
        m_i(i),
        m_j(j){}

    int& m_i;
    const float& m_j;
};

template<class T, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
    return new T(a1, a2);
}

void test()
{

    A* a1 = factory<A>(1, 1.2f);

    //How does this work ?        
    a1->m_i = 2;
}

m_i がどこにバインドされているのかわかりません。

私は基本的に、右辺値参照 (& &&) への左辺値参照を持ちます。これは、ref の折りたたみ規則によって (&) 単なる左辺値参照になります。しかし、何への参照ですか?

4

2 に答える 2

10

m_i がどこにバインドされているのかわかりません。

m_iAのコンストラクタの引数にバインドされています。Aここでのコンストラクタの引数は何ですか?

この場合、は引数を に転送factoryしない(つまり、 を使用しない)ため、 に渡されるのは左辺値です。これは、名前付きであり、名前付きオブジェクトが左辺値であるためです。Astd::forward<>()Aa1

は、 が左辺値か右辺値a1かを判断するのには関係ありません。a1したがって、プログラムの場合のように( )への右辺値参照a1型があっても、パラメーターはそれ自体が名前付きオブジェクトであるため、左辺値です。 intint&&a1

これは、m_iが への lvalue-reference 型を持っているためint、の (lvalue) parameterにバインドm_i できる(そして実際にバインドされている) ことを意味します。これは、返されるときに破棄されます。つまり、ぶら下がり参照が残っています。factorya1factory()

それを逆参照しようとすると (後でプログラムで行うように)、Undefined Behaviorが呼び出されます。

ただし、factory()関数がその引数をのコンストラクターに転送した場合:A

template<class T, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
    return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}

std::forward<>()の機構が左辺値が左辺値のままであり、右辺値が右辺値のままであることを確認するため、これはコンパイラ エラーを引き起こします。左辺値参照を右辺値にバインドしようとする試みは不正であるため、Aのコンストラクターへの呼び出しは失敗します。

于 2013-04-12T10:23:20.580 に答える
3

しかし、何への参照ですか?

これは未定義の動作です。ご想像のとおり、関数のスタックで破棄されたテンポラリへの参照ですfactory。コンパイル時にそのような問題をキャッチするには、使用する必要がありますstd::forward

template<class T, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
    return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}
于 2013-04-12T10:22:36.767 に答える