std :: remove,std :: move(range)和move-from元素

时间:2017-06-26 12:06:56

标签: c++ c++11 move stl-algorithm

看看std :: remove参考我看到了:

template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );

通过移动(通过移动分配)范围中的元素来完成移除。指向新逻辑结束和范围物理结束之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值(根据MoveAssignable后置条件)。

所以,我看到MoveAssignable conept:

t = rv   // Post-condition:The new value of rv is unspecified.

到目前为止,没关系。关于MoveAssignable概念的问题:

std::string s1 = "abc";
std::string s2;
s2 = std::move(s1);
std::cout << s1;    // is this code valid?
s1 = "cde";         // is this code valid?

我可以重复使用&#34;来自&#34;通过读取其值或重新分配其值来变量?

现在我正在查看std :: move引用,它看起来有点令人惊讶:

template< class InputIt, class OutputIt >
OutputIt move( InputIt first, InputIt last, OutputIt d_first );

将范围[first,last]中的元素移动到从d_first开始的另一个范围。 在此操作之后,移动范围内的元素仍将包含相应类型的有效值,但不一定与移动前的值相同。

因此,move-from元素在std :: remove和std :: move中以不同的方式定义,尽管它们应该是相同的。哪一个是正确的?重用(或不使用)移动元素的规则是什么?

1 个答案:

答案 0 :(得分:1)

标准中的实际措辞见[lib.types.movedfrom]部分:

  

可以从([class.copy])移动C ++标准库中定义的类型的对象。可以显式指定或隐式生成移动操作。除非另有规定,否则此类移动对象应置于有效但未指定的状态。

std::move([alg.move])的描述简单地说,元素被移动并且不会对移动的对象做出任何评论。 std::remove([alg.remove])的描述有一个非规范性的说明:

  

注意:范围[ret,last)中的每个元素,其中ret是返回值,具有有效但未指定的状态,因为算法可以通过移动来消除元素最初在该范围内的元素。

所以cppreference碰巧在这两个页面上使用不同的措辞,但它们的含义完全相同。

现在,鉴于std::string s1已被移除,是否有效

std::cout << s1;

是的,它是允许的,因为s1是&#34;有效&#34;,但它无用,因为您无法保证输出的内容。另一方面,

s1 = "cde";

既安全又有用,因为s1的任何先前内容都将被丢弃。

对于&#34;的示例,除非另有说明&#34;,请查看std::unique_ptr<T>的移动赋值运算符([unique.ptr.single.asgn]):

unique_ptr& operator=(unique_ptr&& u) noexcept;
  

效果:将所有权从u转移到*this,就像通过调用reset(u.release())后跟get_deleter() = std::forward<D>(u.get_deleter())一样。

由于u.release()使u为空/ null,我们实际上确保移动的对象将为空/ null。类似的保证是针对移动构造函数和模板化构造函数以及使用不同模板参数的unique_ptr赋值,因此移动的unique_ptr始终为空/ null。