4

以下は安全ですか?最初のクラス メンバーが初期化された後は d にstd::stringなりませんか? move正常に印刷されますが、わかりません。

template <typename T>
class Test
{
public:

    template <typename... Args>
    Test(Args&&... args)
    :  m_one(new T(std::forward<Args>(args)...)),
       m_two(new T(std::forward<Args>(args)...))    // <- Here
    {
    }

private:
    std::unique_ptr<T> m_one;
    std::unique_ptr<T> m_two;
};


class C
{ 
public:

    C(int a, int b, const std::string& c)
    :  m_a(a),
       m_b(b),
       m_c(c)
    {
        std::cout << "ctor a=" << m_a << ", b=" << m_b << ", c=" << m_c << "\n";
    }

    int m_a;
    int m_b;
    std::string m_c;
};


int main()
{
     Test<C> t(1, 2, "3");
}

の 3 番目の ctor パラメータが でCあるため、問題ないと思いますが、r-value refをconst std::string&取るクラスで完全な転送を防ぐにはどうすればよいですか?C(int, int, std::string&&)m_twom_one

Test の cactor を

   template <typename... Args>
   Test(Args&... args)

コンパイルしません。std::forward<Args>(args)...また、 fromm_oneおよびm_twoctorを削除することもありません。

4

1 に答える 1

7

次のようなものを使用したいと思うでしょう:

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

template <typename T>
class Test
{
public:

    template <typename... Args>
    Test(Args&&... args)
    :  m_one(new T(args...)),                    // avoid moving the first time
       m_two(new T(std::forward<Args>(args)...)) // but allowing moving the last time
    {
    }

private:
    std::unique_ptr<T> m_one;
    std::unique_ptr<T> m_two;
};


class C
{
public:

    C(int a, int b, std::string c) // rule of thumb -- if you are going to copy an argument
                                   // anyway, pass it by value.
    :  m_a(a),
       m_b(b),
       m_c(std::move(c)) // you can safely move here since it is the last use. 
    {
        std::cout << "ctor a=" << m_a << ", b=" << m_b << ", c=" << m_c << "\n";
    }

    int m_a;
    int m_b;
    std::string m_c;
};

の場合m_one、引数は左辺値参照を使用するため、移動は行われません。の場合m_two、 はstd::forward必要に応じて右辺値参照を使用します。引数std::stringC値で取得して使用std::moveすると、どちらの場合でも適切に機能します。左辺値参照を渡すと、引数はコピー構築されますが、右辺値参照を渡すと、引数は移動構築されます。いずれの場合も、m_c効率のために引数をメンバーに移動できます。

于 2013-11-27T23:38:45.907 に答える