以下是否安全?在初始化第一个类成员后,std::string
是不是move
d?打印好了,但我不确定。
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");
}
我想这是可以的,因为C
的第三个ctor参数是const std::string&
,但是如何在一个采用r值ref的类中阻止完美转发,例如C(int, int, std::string&&)
那么m_two
将不会收到与m_one
相同的ctor args?
将测试的ctor更改为
template <typename... Args>
Test(Args&... args)
无法编译。也不会从std::forward<Args>(args)...
和m_one
ctors中删除m_two
。
答案 0 :(得分: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::string
参数按C
按值并使用std::move
使其适用于任何一种情况。如果传递左值引用,则参数将被复制构造,但是如果传递右值引用,则参数将被移动构造。在任何一种情况下,您都可以将参数移到m_c
成员中以提高效率。