我可以创建对空可选值的引用吗?

Can I create a reference to the value of an empty optional?

我看到了以下模式several times

// T is a type, this is at namespace scope
std::aligned_storage_t<sizeof(T), alignof(T)> storage;
T &t = reinterpret_cast<T &>(storage);

这与足够的命名空间和命名相结合,为变量的用户提供了一个愉快的界面 (t),同时通过放置 new 和显式析构函数调用。您可以看到它正在运行 here.

现在,std::aligned_storage 很整洁,但是 C++17 为我们提供了一个新工具,用于这种存储与对象生命周期的拆分,即 std::optional

但是,访问 std::optional 值的两种方式(value()operator*)都需要实际存在的值;否则 value() 将抛出 std::bad_optional_access,而 operator* 将触发未定义的行为(通过打破 [optional.observe]§5 中的 requires 子句)。

std::optional<T> storage;
T &t = *storage; // Looks okay, mines bitcoin when you're not looking

std::optional 这样的用法还能以某种方式使用吗?
如果不是,阻止它的原因是什么?

This, coupled with adequate namespacing and naming, provides a pleasant interface (t) to users of the variable, while enabling deferred construction, reinitialization, etc of the actual object on the library side.

不幸的是,使用 t 访问稍后在该地址构造的对象是未定义的行为。这是 reasons 提出 std::launder 的原因之一。

请注意,这种情况不同于 that question. In that question, the reference/pointer is obtained after the object of type T is created (though this may also be undefined 中描述的情况,在 C++17 之后没有 std::launder)。

Is such an usage of std::optional still possible somehow?

正如您所指出的,这是未定义的行为。

If not, what would be a reason for preventing it?

优化器可能会发现该地址与为 T 提供存储的对象相关联,并忽略通过导致未定义行为的类型的 glvalue 对该地址的任何访问。其实原因本质上就是how strict-aliasing rules benefit an optimizer.