使用非指针数据成员移动语义
Move semantics with non-pointer data members
可能已经有人询问并回答了这个问题,但我不知道要搜索什么。
如果数据成员定义了移动赋值运算符,是否可以将移动语义用于非指针数据成员?
假设我有一个 class 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;
};
现在显然我可以有一个像这样的 class 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
从一个实例移动到另一个实例,但是如何正确重置传递给 [=22= 的 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;
};
那么,在移动函数中重置非指针数据成员的符合标准的方法是什么?
包含类型的 assignment/constructors 移动必须使对象处于 "acceptable" 状态,无论该类型对该类型意味着什么。正在移动的类型之外的任何内容都不应负责维护对象的状态。
此外,您要确保在父移动 构造函数 中调用包含类型的移动 构造函数,而不是包含的类型的移动 assignment 正如你在你的例子中:
// 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);
}
可能已经有人询问并回答了这个问题,但我不知道要搜索什么。
如果数据成员定义了移动赋值运算符,是否可以将移动语义用于非指针数据成员?
假设我有一个 class 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;
};
现在显然我可以有一个像这样的 class 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
从一个实例移动到另一个实例,但是如何正确重置传递给 [=22= 的 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;
};
那么,在移动函数中重置非指针数据成员的符合标准的方法是什么?
包含类型的 assignment/constructors 移动必须使对象处于 "acceptable" 状态,无论该类型对该类型意味着什么。正在移动的类型之外的任何内容都不应负责维护对象的状态。
此外,您要确保在父移动 构造函数 中调用包含类型的移动 构造函数,而不是包含的类型的移动 assignment 正如你在你的例子中:
// 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);
}