在实际代码中,构造函数可能非常复杂,因此emplace
of a std::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
。换句话说,在执行嵌入构造函数期间,可选函数会执行以下操作:不包含值.
从实现的角度来看,这意味着首先就地构造该值,然后设置一些簿记变量。情况确实如此MSVC https://github.com/microsoft/STL/blob/f675d68f03cfb7a303cd5408502f2642947d32b7/stl/inc/optional#L119-L120, libc++ https://github.com/llvm/llvm-project/blob/2e1150d8aad60a8a127c10d9cd48c31334493ebf/libcxx/include/optional#L325-L326 and libstdc++ 库 https://github.com/gcc-mirror/gcc/blob/c57a8aea0c3ab8394f7dbfa417ee27b4613f63b7/libstdc%2B%2B-v3/include/std/optional#L250-L252.
Now the 标准的相关部分 https://timsong-cpp.github.io/cppwp/n4861/optional#optional-1 reads
[...]当一个实例optional<T>
包含一个值,这意味着类型 T 的对象,称为可选对象的包含价值,在可选对象的存储中分配。
有趣的是,这并没有使用明确定义的lifetime所包含对象的(我想是因为这可以从外部强制结束,例如othing->~Thing()
),但是术语在存储空间内分配。该标准通常谈到动态内存上下文中的分配,在这些情况下,分配显然会发生before建造。
所以我认为提到的标准库实现不符合要求,簿记变量应该在构建开始之前设置。
在这一假设下,仍然存在一个问题:实现是否比标准更好,而不是后者需要修复或澄清?
我不这么认为:在建造大型物体的过程中完全有效 https://timsong-cpp.github.io/cppwp/n4659/class.init#class.base.init-16并且对于访问已经初始化的子对象很常见,因此对于可选中包含的对象来说这也应该是可能的。
那么我的考虑对吗?或者是我对这个词的解释内分配不正确?对于我的正确做法™ 的观点是否存在反对意见?