const std::optional 的内容是否总是常量?

koa*_*alo 4 c++ c++17

我会假设

std::optional<const std::string>
Run Code Online (Sandbox Code Playgroud)

允许为可选项分配一个新值,但不能更改字符串本身和

const std::optional<const std::string>
Run Code Online (Sandbox Code Playgroud)

两者都做是不可能的。但是下面的呢?

const std::optional<std::string>
Run Code Online (Sandbox Code Playgroud)

Art*_*yer 8

然后让我们做一些测试:

#include <string>
#include <optional>

int main() {
    using n_c = std::optional<const std::string>;
    using c_n = const std::optional<std::string>;
    using n_n = std::optional<std::string>;

    n_c opt_n_c{"a"};
    c_n opt_c_n{"a"};
    n_n opt_n_n{"a"};

    opt_n_c.emplace("b");
    // opt_c_n.emplace("b");
    opt_n_n.emplace("b");

    // opt_n_c->pop_back();
    // opt_c_n->pop_back();
    opt_n_n->pop_back();
}
Run Code Online (Sandbox Code Playgroud)

注释掉的行不起作用。

可以这样想:非常量std::optional<T>可以没有值或 a T,它可以被替换(不使用T::operator=,只是破坏当前持有的,T如果它存在并构造一个新的)。非常量std::optional<const T>可以做完全相同的事情,虽然const T可能没有operator=,所以你不能改变持有的价值,但你仍然可以改变持有的价值。Aconst std::optional<T>也是“逻辑常量”。如果 aconst std::optional<T>等于 another const std::optional<T>,并且没有触及非常量引用,则它们(应该)始终保持相等,因此保持的值(应该)不会改变。这就是为什么它们返回对所持有的值的常量引用,这也是为什么const std::optional<T>const std::optional<const T>实际上是相同的。


Bar*_*rry 7

但下面的情况又如何呢?

const std::optional<std::string>
Run Code Online (Sandbox Code Playgroud)

标准库中的所有内容都将是const-正确的 - 因此访问器optional都是const适当的 - 限定的。调用value()oroperator*()将会const optional<T>给你一个const T&(或const T&&),而不是一个T&

您无法直接访问可修改的引用。

请注意,如果您有const optional<int*>, 另一方面,则是指针本身const- 而不是被指向者。所以这很好:

int i = 42;
const std::optional<int*> opt(&i);
*opt.value() = 57;
assert(i == 57);
Run Code Online (Sandbox Code Playgroud)

a 的内容是const std::optionalalways吗const

现在从技术上讲,上述内容实际上并没有回答您的问题。Aconst std::optional<std::string>不持有 a const std::string- 它持有std::string仅公开const访问的 a。所以......从技术上讲......但真的从来没有认真地这样做,这很糟糕......这是明确定义的:

const std::optional<std::string> opt("hello"s);
const_cast<std::string&>(opt.value()) = "I am a bad person and I feel bad"s;
Run Code Online (Sandbox Code Playgroud)

因为string本身从未被创建为const