为什么不这样:(vs2010)在类中移动向量?
#include <vector>
class MoveTest
{
public:
std::vector<int> m_things;
};
int _tmain(int argc, _TCHAR* argv[])
{
MoveTest m;
m.m_things.push_back(12);
MoveTest m2 = std::move(m);
// std::vector has been copied, not moved
return 0;
}
这是否意味着每个使用std :: vector(以及其他可移动类)的类都应该有一个显式的移动构造函数和赋值?
答案 0 :(得分:9)
除了已经提供的关于这些规则的迟到与vs2010发布时相比的好答案之外,
隐式生成的移动构造函数的规则是:
如果X类的定义有 没有明确宣布一个举动 构造函数,一个将隐式 当且仅当
声明为默认值
- X没有用户声明的复制构造函数,
- X没有用户声明的复制赋值运算符
- X没有用户声明的移动赋值运算符
- X没有用户声明的析构函数,
- 移动构造函数不会被隐式定义为已删除。
隐式生成的移动赋值运算符的规则遵循上述模式。
隐式生成复制构造函数的规则稍微改变了!
如果类定义没有 显式声明一个复制构造函数, 一个被隐含地宣布。如果 类定义声明了一个动作 构造函数或移动赋值 运算符,隐式声明的副本 构造函数定义为已删除; 否则,它被定义为默认 (8.4)。后一种情况已被弃用 如果类具有用户声明的副本 赋值运算符或用户声明的 析构函数。
类似地,对于复制赋值运算符:
如果类定义没有 明确声明副本分配 运算符,一个是隐式声明的。 如果类定义声明了一个 移动构造函数或移动赋值 运算符,隐式声明的副本 赋值运算符定义为 删除;否则,它被定义为 违约(8.4)。后一种情况是 如果班级有,则弃用 用户声明的复制构造函数或 用户声明的析构函数。
底线:3的规则现在是5的规则。您可以忽略全部5(如果默认行为适合您),或者您需要考虑(并可能定义)所有5:
答案 1 :(得分:7)
使用完全符合C ++ 0x编译器,您的类将具有移动成员的隐式移动构造函数,以及隐式复制构造函数。在此示例中,将使用隐式移动构造函数。
但是,在委员会同意此规则之前,MSVC2010已经出现,因此您必须明确地编写移动构造函数。然后,您还需要定义默认构造函数和复制构造函数,并且可能还应该定义移动赋值和复制赋值以获得良好的度量:
class MoveTest
{
public:
std::vector<int> m_things;
MoveTest()
{}
MoveTest(MoveTest&& other):
m_things(std::move(other.m_things))
{}
MoveTest(MoveTest const& other):
m_things(other.m_things)
{}
MoveTest& operator=(MoveTest&& other)
{
MoveTest temp(std::move(other));
std::swap(*this,temp);
return *this;
}
MoveTest& operator=(MoveTest const& other)
{
if(&other!=this)
{
MoveTest temp(other);
std::swap(*this,temp);
}
return *this;
}
};
答案 2 :(得分:2)
MoveTest
类没有移动构造函数,因此它使用了默认的复制构造函数。
复制构造函数复制成员元素。 : - )
可能存在C ++ 11 conformat编译器生成默认移动构造函数的情况,但我不确定最终规则的结束位置(存在很晚的更改)。 VS2010太老了,也不知道。
答案 3 :(得分:1)
VS2010没有隐式移动构造函数。你必须明确地写一个。