std :: optional的值的地址是否稳定?

Rum*_*rak 17 c++ std language-lawyer c++17

说我有一个std::optional<T>.我重置并多次赋值.对于给定的可选值,值的地址(如果存在)是否始终相同?

换一种说法:

#include <cassert>
#include <optional>
#include <string>

template<typename T>
auto test()
{
    auto opt = std::optional<T>{T{}};
    auto* ptr = &*opt;

    opt.reset();
    opt = T{};

    assert(ptr == &*opt); // Can this assert fail?
}

int main()
{
    test<int>();
    test<double>();
    test<std::string>();
    // ...
}
Run Code Online (Sandbox Code Playgroud)

标准是否保证了值的地址的稳定性?

Edg*_*jān 13

标准是否保证了值的地址的稳定性?

从我的观点来看,未指明地址是否稳定.

在形式上,标准仅保证对于包含在std::optional其中的对象没有动态分配,并且包含对象存储为以下部分的一部分std::optional:

23.6.3类模板可选[optional.optional]

任何给定时间的任何可选实例都包含值或不包含值.当可选实例包含值时,意味着在可选对象的存储中分配类型为T的对象(称为可选对象的包含值).不允许实现使用额外的存储(例如动态内存)来分配其包含的值.包含的值应分配在可选存储区域中,适合于类型T对齐.当可选类型的对象在上下文中转换为bool时,如果对象包含值,则转换返回true; 否则转换返回false.

实际存储机制由特定实现定义,因此,地址可能会发生变化.

然而,在实践中,实现将使用类似aligned_storage(参见boost 实现)或union(如gcc 所做的)并保持包含对象的地址相同.