常量的内容是否总是恒量?
Is the content of a const std::optional always const?
我会假设
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
.
- 是否可以同时声明一个类成员的常量/非常量?
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- 是否应避免从非常量迭代器转换为常量迭代器?
- 是否有内置方法可以强制转换为不同的基础类型,但保留常量限定符?
- 将常量字符串添加到非常量字符串是否会给出常量字符串
- 是否可以使用 new 指定具有宏常量的动态分配数组的元素?
- 是否可以跨 dll 边界返回常量引用/指向 std::vectors?
- 检查输入 std::array 指针数据是否等于某个常量数组
- C++中大多数/所有 setter 函数的参数是否应该写为常量引用?
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- C++ - 是否将常量幻数放入命名空间
- c++ 编译器是否保护常量内存地址免受任何更改?
- 这些语句是否等效(静态变量、常量变量和泛型)
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 是否将命名空间范围文件本地 (.cpp) 常量放在匿名命名空间中
- C++中是否有任何常量可以用作比较中的最小值/最大值
- 当通过常量和不是字符串的最佳选择时,是否有任何情况?
- C++ 多态性:如果派生类中的虚函数在基类中声明了常量,是否需要将其声明为常量
- 是否可以重用通常的迭代器来构建常量迭代器?
- 如果我公开常量和非常量 API,我是否破坏了常量正确性?