【发布时间】:2016-09-18 22:10:12
【问题描述】:
可能已经有人问过并回答过了,但我不知道要搜索什么。
如果数据成员定义了移动赋值运算符,移动语义是否可以用于非指针数据成员?
假设我有一个类 M 定义 M::operator=(M&&) 像这样:
template <class T>
class M
{
public:
M()
{
mem_M = new T;
}
M& operator=(M&& src)
{
if (this != &src)
{
mem_M = src.mem_M;
src.mem_M = nullptr;
}
return *this;
}
private:
T* mem_M;
};
现在显然我可以有一个像这样的C<T> 类,带有一个不使用T 的移动赋值运算符的移动构造函数:
template <class T>
class C
{
public:
C ()
{
mem_C = new T;
}
C (C&& rhs)
{
mem_C = rhs.mem_C;
rhs.mem_C = nullptr;
}
private:
T* mem_C;
};
但是,如果我希望C<T>::mem_C 不是指针而是普通成员怎么办,我将如何处理移动函数中的C<T>::mem_C?我当然可以调用移动赋值运算符T::operator=(T&&) 将归档的mem_C 从一个实例移动到另一个实例,但是如何正确重置传递给C<T>::C(C&&) 的C 实例?
这至少在我看来是错误的:
template <class T>
class C
{
public:
C ()
{
mem_C = T();
}
C (C<T>&& rhs)
{
mem_C = std::move(rhs.mem_C);
rhs.mem_C = T(); // ?? like this?
}
private:
T mem_C;
};
那么,在移动函数中重置非指针数据成员的标准兼容方法是什么?
【问题讨论】:
-
指针是“普通成员”的子集。您似乎在问移动类类型和非类类型之间的区别
-
mem_C = T();应该被移除,对象已经被构造,所以这只是浪费时间和资源。 -
在这种情况下,您可以并且应该使用默认的移动赋值运算符(请参阅Rule of zero)
-
@M.M 但如果
mem_C是一百万个元素的向量?释放该空间是否不值得花时间重新初始化mem_C。 -
嗯?例如,如果
T是vector<bla>,那么当构造函数运行时它是一个空向量;将其设置为空向量不会释放任何东西,只会浪费时间。
标签: c++ pointers move-semantics