常量的内容是否总是恒量?

Is the content of a const std::optional always const?

本文关键字:是否 常量      更新时间:2023-10-16

我会假设

std::optional<const std::string>

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

const std::optional<const std::string>

不可能两者兼而有之。但是下面呢?

const std::optional<std::string>

那么让我们做一些测试:

#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();
}

注释掉的行不起作用。

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

但是下面呢?

const std::optional<std::string>

标准库中的所有内容都将const正确 - 因此optional上的访问器都const适当地限定。在const optional<T>上打电话给value()operator*()会给你一个const T&(或const T&&),永远不会T&

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

请注意,如果你有一个const optional<int*>,另一方面,const的是指针本身 - 而不是脚尖。所以这很好:

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

const std::optional的内容总是const吗?

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

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

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

相关文章: