在执行构造函数时 std::optional 不应该包含它的值吗?

时间:2021-04-29 11:28:22

标签: c++ c++17 language-lawyer c++-standard-library stdoptional

在实际代码中,构造函数可能非常复杂,因此 emplacestd::optional 可以查询可选本身的状态。发生这种情况时,通常会比较复杂,但这是一个(人为的)最小示例:

#include <iostream>
#include <optional>

struct Thing {
    Thing();
};

std::optional<Thing> othing;

Thing::Thing() {
    std::cout << othing.has_value() << std::endl;
}

int main() {
    othing.emplace();
}

对于所有三个主要的标准库实现,这会产生 false。换句话说,在嵌入构造函数的执行过程中,可选项不包含值

从实现的角度来看,这意味着首先就地构造值,然后设置一些簿记变量。而这在 MSVClibc++libstdc++ 中确实如此。

现在 relevant part of the standard 读取

<块引用>

[...] 当 optional<T> 的实例包含一个值时,表示一个 T 类型的对象,称为可选对象的包含的值 em>,在可选对象的存储中分配。

有趣的是,这并没有使用所包含对象的明确定义的lifetime(我想是因为这可以从外部强行结束,例如othing->~Thing()),但是术语在存储中分配。该标准通常在动态内存的上下文中谈到分配,在这些情况下,分配显然发生在构造之前

所以我认为提到的标准库实现不合规,簿记变量应该在构建开始之前设置。

在这个假设下,一个问题仍然存在:实现是否比标准更好,而不是后者需要修复或澄清? 我不这么认为:在构造大对象期间,访问已经初始化的子对象是 perfectly valid 并且很常见,因此这对于包含在可选对象中的对象也应该是可能的。

那么我的考虑对吗?或者我对分配范围这个词的解释不正确?是否有反对我的 RightThing™ 的观点的论据?

0 个答案:

没有答案
相关问题