为什么移动std :: optional不重置状态 [英] Why does moving std::optional not reset state

查看:100
本文介绍了为什么移动std :: optional不重置状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

得知[c0>的move构造函数(以及该问题的赋值)没有重置可选的move from,我感到非常惊讶,如[19.6.3.1/7]所示,其中指出"bool(rhs )保持不变."

I was rather surprised to learn that the move constructor (and assignment for that matter) of std::optional does not reset the optional moved from, as can be seen in [19.6.3.1/7] which states "bool(rhs) is unchanged."

这也可以通过以下代码看到:

This can also be seen by the following code:

#include <ios>
#include <iostream>
#include <optional>
#include <utility>

int main() {
  std::optional<int> foo{ 0 };
  std::optional<int> bar{ std::move(foo) };

  std::cout << std::boolalpha
            << foo.has_value() << '\n'  // true
            << bar.has_value() << '\n'; // true
}

这似乎与在标准库中移动的其他实例(例如,在std::vector中)相矛盾,在该实例中,从移出的容器通常以某种方式重置(在矢量的情况下,保证之后会为空)以使其无效",甚至如果其中包含的对象本身已被移走.该决定是否应支持这种或潜在的使用案例,例如试图模仿相同类型的非可选版本的行为?

This seems to contradict other instances of moving in the standard library such as with std::vector where the container moved from is usually reset in some way (in vector's case it is guaranteed to be empty afterwards) to "invalidate" it even if the objects contained within it themselves have been moved from already. Is there any reason for this or potential use case this decision is supposed to support such as perhaps trying to mimic the behavior of a non-optional version of the same type?

推荐答案

除非另行指定,否则将将类类型的移出对象保留为有效但未指定状态.不一定是重置状态",也绝对不是无效".

Unless otherwise specified, a moved-from object of class type is left in a valid but unspecified state. Not necessarily a "reset state", and definitely not "invalidated".

对于基本类型,移动与复制相同,即源不变.

For primitive types , moving is the same as copying, i.e. the source is unchanged.

具有原始成员的类类型的默认move-constructor将移动每个成员,即,保持原始成员不变;用户定义的move构造函数可能会或可能不会重置"它们.

The defaulted move-constructor for a class type with primitive members will move each member, i.e. leave the primitive members unchanged; a user-defined move constructor might or might not "reset" them.

从源移出的向量中可能有也可能没有元素.我们希望这样做不会,因为这样做效率很高,但是不能依靠它.

A moved-from vector may or may not still have elements in it. We would expect it not to, since that's efficient, but it cannot be relied on.

由于小字符串优化,从std::string移出的std::string可能仍包含元素.

A moved-from std::string may still have elements in it, because of Small String Optimization.

move实际上是由标准(C ++ 17 [optional.ctor]/7)指定的.定义为对包含的类型(如果存在)执行move.它不会将有价期权变成无价期权.

move on std::optional is actually specified by the standard (C++17 [optional.ctor]/7). It is defined as doing move on the contained type, if present. It does not turn a valued optional into a valueless optional.

因此,实际上期望您的代码输出true true,并且foo中的实际包含值也应保持不变.

So it is actually expected that your code outputs true true, and the actual contained value in foo should stay the same too.

关于为什么 std::optional的move-constructor的问题是这样定义的:我不能肯定地说.但是optional不同于最大大小为1的向量.它更像是带有有效性标记的变量.因此,将optional就像移动变量一样有意义.

Regarding the question of why std::optional 's move-constructor is defined this way: I can't say for sure; but an optional is not like a vector with max size of 1. It's more like a variable with a validity flag tacked on. Accordingly, it makes sense for moving an optional to be like moving the variable.

如果移动optional离开旧的空",那么a = std::move(b);会调用b的托管对象的析构函数,这是意外的(至少对我来说是这样).

If moving an optional left the old one "empty", then a = std::move(b); would invoke the destructor of b's managed object, which would be unexpected (to me, at least).

这篇关于为什么移动std :: optional不重置状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆