C++ 具有非指针数据成员的移动语义
也许这个问题已经被问到和回答了,但我不知道该搜索什么 如果数据成员定义了移动赋值运算符,则可以将移动语义用于非指针数据成员吗 假设我有一个类C++ 具有非指针数据成员的移动语义,c++,pointers,move-semantics,C++,Pointers,Move Semantics,也许这个问题已经被问到和回答了,但我不知道该搜索什么 如果数据成员定义了移动赋值运算符,则可以将移动语义用于非指针数据成员吗 假设我有一个类M,它定义了M::operator=(M&&),如下所示: template <class T> class M { public: M() { mem_M = new T; } M& operator=(M&& src) { if (this !
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::mem_C
不是指针而是普通成员,我将如何处理move函数中的C::mem_C
?当然,我可以调用move assignment操作符T::operator=(T&&&)
将字段mem_C
从一个实例移动到另一个实例,但是如何正确重置传递给C::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;
};
模板
C类
{
公众:
C()
{
mem_C=T();
}
C(C&rhs)
{
mem_C=std::move(rhs.mem_C);
像这样的rhs.mem_C=T();/?
}
私人:
T mem_C;
};
那么,在移动函数中重置非指针数据成员的标准兼容方式是什么呢?所包含类型的移动赋值/构造函数必须使对象保持“可接受”状态,无论这对该类型意味着什么。要移动的类型之外的任何内容都不应负责维护对象的状态 另外,您要确保调用的是父移动构造函数中包含类型的移动构造函数,而不是示例中包含类型的移动赋值:
// move constructor calls move constructor of contained elements
C (C<T>&& rhs) : mem_c(std::move(rhs.mem_c))
{
// anything in here is using already-constructed data members
}
// move assignment calls move assignment of contained elements
C & operator=(C<T>&& rhs) {
mem_c = std::move(rhs.mem_c);
}
//move构造函数调用包含元素的move构造函数
C(C&&rhs):mem_C(标准::move(rhs.mem_C))
{
//这里的任何内容都使用已构造的数据成员
}
//移动分配调用包含元素的移动分配
C&operator=(C&rhs){
mem_c=std::move(rhs.mem_c);
}
所包含类型的移动赋值/构造函数必须使对象保持“可接受”状态,无论这对该类型意味着什么。要移动的类型之外的任何内容都不应负责维护对象的状态
另外,您要确保调用的是父移动构造函数中包含类型的移动构造函数,而不是示例中包含类型的移动赋值:
// move constructor calls move constructor of contained elements
C (C<T>&& rhs) : mem_c(std::move(rhs.mem_c))
{
// anything in here is using already-constructed data members
}
// move assignment calls move assignment of contained elements
C & operator=(C<T>&& rhs) {
mem_c = std::move(rhs.mem_c);
}
//move构造函数调用包含元素的move构造函数
C(C&&rhs):mem_C(标准::move(rhs.mem_C))
{
//这里的任何内容都使用已构造的数据成员
}
//移动分配调用包含元素的移动分配
C&operator=(C&rhs){
mem_c=std::move(rhs.mem_c);
}
指针是“普通成员”的子集。您似乎在询问移动类类型和非类类型之间的区别mem_C=T()代码>应该被删除,对象已经被构造,因此这只会浪费时间和资源。在这种情况下,您可以也应该使用默认的移动分配运算符(请参见)@M.M,但是如果mem_C
是一百万个元素的向量?释放空间不值得花时间重新初始化mem\u C
?例如,如果T
是vector
,那么当构造函数运行时,它是一个空向量;将其设置为空向量不会释放任何内容,只会浪费时间。指针是“普通成员”的子集。您似乎在询问移动类类型和非类类型之间的区别mem_C=T()代码>应该被删除,对象已经被构造,因此这只会浪费时间和资源。在这种情况下,您可以也应该使用默认的移动分配运算符(请参见)@M.M,但是如果mem_C
是一百万个元素的向量?释放空间不值得花时间重新初始化mem\u C
?例如,如果T
是vector
,那么当构造函数运行时,它是一个空向量;将其设置为空向量不会释放任何内容,只会浪费时间。