const int * :指针本身可变,指向的值不可变
int * const :指针本身不可变,指向的值可变
转化 const int * -> int * const 会报错
转化 int * const -> const int * 可以进行
从语义上来讲比较好理解,但从形式上来看,两者分别都有一个不可变的量,那为什么转化时一个方向可行,而另一个不可行?考虑了一下,可能源自于 指针和值不是一个层次上的东西 ,但又不知道应该怎么说清楚呢?
const int * :指针本身可变,指向的值不可变
int * const :指针本身不可变,指向的值可变
转化 const int * -> int * const 会报错
转化 int * const -> const int * 可以进行
从语义上来讲比较好理解,但从形式上来看,两者分别都有一个不可变的量,那为什么转化时一个方向可行,而另一个不可行?考虑了一下,可能源自于 指针和值不是一个层次上的东西 ,但又不知道应该怎么说清楚呢?
6 回答6.9k 阅读✓ 已解决
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
假设这里讨论的是隐式转换(static_cast同理):
底层const遵从qualification conversions:目标类型必须more qualifed。就是const只能多不能少。
顶层const规则复杂些,对于类类型,是否能转换取决于转换构造函数和转换函数。对于非类类型,不存在顶层const转换一说。Clause 4 standard conversions对于顶层const只字未提。
在这里另讨论几种有顶层const参与的情况:
表达式:
赋值:
初始化:
也就是说当需求的是prvalue时,不存在const prvalue。关于glvalue,有如下约定:
这一段约定了隐式转换后的value category。当隐式转换的结果是prvalue时,不存在const一说;而当结果是glvalue时,转换的目标类型得是lvalue reference或rvalue reference。在这种情况下,若如下初始化成立,则能转换:
T &t = e;
T &&t = e;
const T &t = e;
const T &&t = e;
reference-compatible约束了是否能初始化。这里的规则类似qualification conversion的规则。另外这些const已经是底层const了。
PS:在qualification conversions处有一个脚注:“These rules ensure that const-safety is preserved by the conversion.”。一切implicit const conversion,约定的也好,假想的也好,只要能保证const的安全性,就没毛病。如果某个const conversion保证了const的安全性,但是却因违背了其他某些条款而不能实现,那大概这语言药丸。滑稽