Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
450 views
in Technique[技术] by (71.8m points)

const int * 和 int * const 的类型转换

const int * :指针本身可变,指向的值不可变

int * const :指针本身不可变,指向的值可变

转化 const int * -> int * const 会报错

转化 int * const -> const int * 可以进行

从语义上来讲比较好理解,但从形式上来看,两者分别都有一个不可变的量,那为什么转化时一个方向可行,而另一个不可行?考虑了一下,可能源自于 指针和值不是一个层次上的东西 ,但又不知道应该怎么说清楚呢?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

假设这里讨论的是隐式转换(static_cast同理):

底层const遵从qualification conversions:目标类型必须more qualifed。就是const只能多不能少。

4.1 Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions.

4.4.1 A prvalue of type “pointer to cv1 T” can be converted to a prvalue of type “pointer to cv2 T” if “cv2 T” is more cv-qualified than “cv1 T”.

顶层const规则复杂些,对于类类型,是否能转换取决于转换构造函数和转换函数。对于非类类型,不存在顶层const转换一说。Clause 4 standard conversions对于顶层const只字未提。


在这里另讨论几种有顶层const参与的情况:

表达式:

5.8 [...] [Note: Because cv-qualifiers are removed from the type of an expression of non-class type when the expression is converted to a prvalue, an lvalue expression of type const int can, for example, be used where a prvalue expression of type int is required. —end note]

赋值:

3.10.1 [...] the built-in assignment operators expect that the left operand is an lvalue and that the right operand is a prvalue and yield an lvalue as the result.

3.10.2 Whenever a glvalue appears in a context where a prvalue is expected, the glvalue is converted to a prvalue; [...]

3.10.4 Class prvalues can have cv-qualified types; non-class prvalues always have cv-unqualified types.

初始化:

8.5.16 [...] [ Note: An expression of type “cv1 T” can initialize an object of type “cv2 T” independently of the cv-qualifiers cv1 and cv2. [...]

也就是说当需求的是prvalue时,不存在const prvalue。关于glvalue,有如下约定:

4.3 An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t (8.5).[...] The effect of either implicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type (8.3.2), an xvalue if T is an rvalue reference to object type, and a prvalue otherwise. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue.

这一段约定了隐式转换后的value category。当隐式转换的结果是prvalue时,不存在const一说;而当结果是glvalue时,转换的目标类型得是lvalue reference或rvalue reference。在这种情况下,若如下初始化成立,则能转换:

T &t = e;
T &&t = e;
const T &t = e;
const T &&t = e;

8.5.3.4 Given types “cv1 T1” and “cv2 T2,” “cv1 T1” is reference-related to “cv2 T2” if T1 is the same type as T2, or T1 is a base class of T2. “cv1 T1” is reference-compatible with “cv2 T2” if T1 is reference-related to T2 and cv1 is the same cv-qualification as, or greater cv-qualification than, cv2.

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的安全性,但是却因违背了其他某些条款而不能实现,那大概这语言药丸。滑稽


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...