我已经在C ++ 11中测试过移动语义。我用移动构造函数编写了一个类。
class DefaultConstructor
{
public:
DefaultConstructor(std::vector<int> test) :
m_vec(std::forward<std::vector<int>>(test))
{
};
DefaultConstructor(DefaultConstructor &&def) :
m_vec(std::forward<std::vector<int>>(def.m_vec))
{
}
DefaultConstructor& operator=(DefaultConstructor&& def) {
m_vec = std::move(def.m_vec);
return *this;
}
DefaultConstructor& operator=(const DefaultConstructor&) = delete;
DefaultConstructor(DefaultConstructor &) = delete;
std::vector<int> m_vec;
};
我写了一个使用移动语义的主函数。我理解移动语义中发生的事情,它是很棒的工具。但是有些行为对我来说是不可解释的。当我为我调用主函数DefaultConstructor testConstructor2 = std::move(testConstructor);
时,应调用DefaultConstructor& operator=(DefaultConstructor&& def)
。但是Visual Studio 2015调用了移动构造函数。
int main()
{
std::vector<int> test = { 1, 2, 3, 4, 5 };
DefaultConstructor testConstructor(std::move(test));
DefaultConstructor testConstructor2 = std::move(testConstructor);
DefaultConstructor &testConstructor3 = DefaultConstructor({ 6, 7, 8, 9 });
DefaultConstructor testConstructor4 = std::move(testConstructor3);
swapMove(testConstructor, testConstructor2);
}
好吧我想也许不再需要= Move Operator了。但我尝试了一个SwapMove功能。此函数调用= move运算符。
template<typename T>
void swapMove(T &a, T &b)
{
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
有人可以解释这两个电话的区别究竟是什么?不应该是来电a = std::move(b);
和DefaultConstructor testConstructor2 = std::move(testConstructor);
有相同的行为吗?
答案 0 :(得分:8)
语法
DefaultConstructor testConstructor2 = something;
始终调用构造函数,因为对象testConstructor2
尚不存在。 operator =只能在已经构造的对象的上下文中调用。
答案 1 :(得分:6)
此:
T foo = bar;
被称为copy-initialization。它通常(但不总是)等同于:
T foo(bar);
不同之处在于后者是对T
构造函数的直接函数调用,而前者试图构造从decltype(bar)
到T
的隐式转换序列。因此,存在直接初始化成功但复制初始化可能失败的情况。无论哪种方式,初始化都是初始化:它是构造函数调用,而不是赋值调用。
在我们的例子中,这两行完全相同:
DefaultConstructor testConstructor2 = std::move(testConstructor);
DefaultConstructor testConstructor2{std::move(testConstructor)};
并且他们都没有打电话给DefaultConstructor::operator=
。
答案 2 :(得分:2)
DefaultConstructor testConstructor2 = std::move(testConstructor);
是施工,而非作业。它与C ++ 11之前的相同类型的代码中的复制构造与赋值完全类似。