c++ - 为什么移动 std::optional 不会重置状态
问题描述
我很惊讶地得知移动构造函数(以及相关的赋值)std::optional
不会重置可选的移动自,正如在 [19.6.3.1/7] 中看到的那样,它声明“bool(rhs) 未更改”。
这也可以通过以下代码看出:
#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
容器移动的位置通常以某种方式重置(在向量的情况下,它保证之后为空)以使其“无效”,即使其中包含的对象也是如此自己已经搬离了。这个决定应该支持这个或潜在的用例是否有任何理由,例如可能试图模仿同一类型的非可选版本的行为?
解决方案
除非另有说明,否则类类型的移出对象将处于有效但未指定的状态。不一定是“重置状态”,也绝对不是“无效”。
对于原始类型,移动与复制相同,即源不变。
具有原始成员的类类型的默认移动构造函数将移动每个成员,即保持原始成员不变;用户定义的移动构造函数可能会也可能不会“重置”它们。
移出的向量中可能有也可能没有元素。我们希望它不会,因为这是有效的,但不能依赖它。
由于小字符串优化,一个被移动的std::string
对象可能仍然有元素。
move
onstd::optional
实际上是由标准(C++17 [optional.ctor]/7)指定的。它被定义为move
在包含的类型上执行(如果存在)。它不会将有价值的可选项变成无价值的可选项。
因此,实际上预计您的代码输出true true
和实际包含的值foo
也应该保持不变。
关于为什么 std::optional
's move-constructor 是这样定义的问题:我不能肯定地说;但 anoptional
不像最大大小为 1 的向量。它更像是一个附加了有效性标志的变量。optional
因此,移动 an就像移动变量是有意义的。
如果将optional
旧的左移“空”,a = std::move(b);
则将调用托管对象的析构函数b
,这将是出乎意料的(至少对我而言)。
推荐阅读
- opencv - 用 VP9 编码 mp4 视频时应该使用什么fourcc?
- snowflake-cloud-data-platform - 雪花 - 使用舞台区域失败。原因:[您提供的 AWS 访问密钥 ID 无效。]
- javascript - 根据字母后出现的数字拆分字符串
- r - 遍历 purrr:map 时随机值重复
- vue.js - 如何仅使用完整日历和 Vue js 为 LoggedIn 用户显示事件?
- nearprotocol - 你如何为 Prometheus 设置配置文件?
- python - pandas groupby 数据帧 2 基于数据帧 1
- android - 使用 ANDROIDX_TEST_ORCHESTRATOR 时未找到测试
- sql - EF - 在 DevArt EntityDeveloper 和 Syncfusion WinForm 网格之间映射外键
- python - 在 keras 损失函数中拆分数据类型(相当于损失函数中的 if 语句?)