说我有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>();
// ...
}
标准是否保证了值的地址的稳定性?
答案 0 :(得分:13)
标准是否保证了值的地址的稳定性?
从我的角度来看,未指定地址是否稳定。
正式地,标准仅保证std::optional
中包含的对象没有动态分配,并且包含对象存储为std::optional
的一部分:
23.6.3类模板可选[optional.optional]
任何给定时间的任何可选实例都包含一个值 或者不包含值。 当一个可选实例包含时 一个值,它表示一个T类型的对象,简称为 可选对象的包含值,是在存储内分配的 可选对象。不允许使用实现 额外的存储,如动态内存,来分配其包含的内容 值。所包含的值应分配在该区域内 可选存储适合于类型T对齐。当一个对象时 type optional是从上下文转换为bool的转换 如果对象包含值,则返回true;否则转换 返回false。
实际存储机制由特定实现定义,因此,地址可能会发生变化。
但实际上,实现将使用aligned_storage
(请参阅 boost implementation)或union
(作为 gcc does)并保持包含对象的地址相同。