实现移动构造函数和移动赋值运算符时,通常会编写如下代码:
p = other.p;
other.p = 0;
隐式定义的移动操作将使用以下代码实现:
p = std::move(other.p);
哪个是错误的,因为移动指针变量不将其设置为null。这是为什么?是否有任何情况我们希望移动操作保持原始指针变量不变?
注意:通过“移动”,我不只是表示子表达式std::move(other.p)
,我的意思是整个表达式p = std::move(other.p)
。那么,为什么没有特殊的语言规则说“如果赋值的右侧是指针xvalue,则在赋值发生后将其设置为null。”?
答案 0 :(得分:31)
移动它后将原始指针设置为null意味着指针代表所有权。但是,许多指针用于表示关系。此外,长期以来,建议所有权关系的表示方式与使用原始指针的方式不同。例如,您引用的所有权关系由std::unique_ptr<T>
表示。如果您希望隐式生成的移动操作处理您的所有权,您需要做的就是使用实际代表(并实现)所需所有权行为的成员。
此外,生成的移动操作的行为与复制操作的行为一致:它们也不做任何所有权假设,也不做例如:复制指针时的深层复制。如果您希望这种情况发生,您还需要创建一个合适的类来编码相关的语义。
答案 1 :(得分:6)
移动渲染移动的对象“无效”。 不会自动将其设置为安全的“空”状态。按照C ++长期以来的原则“不为你不使用的东西买单”,如果你需要,那就是你的工作。
答案 2 :(得分:4)
我认为答案是:自己实现这样的行为非常简单,因此标准认为没有必要对编译器本身施加任何规则。 C ++语言是巨大的,并不是在使用之前可以想象的一切。以C ++的模板为例。它最初并不是按照它今天使用的方式设计的(即它的元编程能力)。所以我认为,标准只是赋予了自由,并没有为std::move(other.p)
制定任何具体规则,遵循其中一个设计原则:“你不为你不支付的费用用“
虽然std::unique_ptr
是可移动的,但不可复制。因此,如果你想要可移动和可复制的指针语义,那么这里有一个简单的实现:
template<typename T>
struct movable_ptr
{
T *pointer;
movable_ptr(T *ptr=0) : pointer(ptr) {}
movable_ptr<T>& operator=(T *ptr) { pointer = ptr; return *this; }
movable_ptr(movable_ptr<T> && other)
{
pointer = other.pointer;
other.pointer = 0;
}
movable_ptr<T>& operator=(movable_ptr<T> && other)
{
pointer = other.pointer;
other.pointer = 0;
return *this;
}
T* operator->() const { return pointer; }
T& operator*() const { return *pointer; }
movable_ptr(movable_ptr<T> const & other) = default;
movable_ptr<T> & operator=(movable_ptr<T> const & other) = default;
};
现在你可以编写类,而无需编写自己的move-semantics:
struct T
{
movable_ptr<A> aptr;
movable_ptr<B> bptr;
//...
//and now you could simply say
T(T&&) = default;
T& operator=(T&&) = default;
};
请注意,您仍然需要编写复制语义和析构函数,因为movable_ptr
是不是智能指针。
答案 3 :(得分:0)
例如,如果您有指向共享对象的指针。请记住,移动对象后必须保持内部一致状态,因此将不能为空的指针设置为空值是不正确的。
即:
struct foo
{
bar* shared_factory; // This can be the same for several 'foo's
// and must never null.
};
修改强>
以下是标准中MoveConstructibe
的引用:
T u = rv;
...
rv’s state is unspecified [ Note:rv must still meet the requirements
of the library component that is using it. The operations listed in
those requirements must work as specified whether rv has been moved
from or not.
答案 4 :(得分:0)
我认为,与众不同的是,一方面是完全吹制的物体,另一方面是POD。