4

以下安全吗?第一个类成员初始化后不会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");
}

我想这没关系,因为 is 的第三个 ctor 参数Cconst std::string&但是我如何防止在一个采用 r 值 ref 的类中完美转发,例如C(int, int, std::string&&),因为 thenm_two不会收到与 相同的 ctor args m_one

将 Test 的 ctor 更改为

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

不编译。也不会删除std::forward<Args>(args)...fromm_onem_twoctors。

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_twostd::forward将酌情使用右值引用。按值获取std::string参数C并使用std::move使其在任何一种情况下都能正常工作。如果传递左值引用,则参数将被复制构造,但如果传递右值引用,则参数将被移动构造。无论哪种情况,您都可以将参数移到您的m_c成员中以提高效率。

于 2013-11-27T23:38:45.907 回答