Heim > Fragen und Antworten > Hauptteil
const int *: Der Zeiger selbst ist veränderlich, aber der Wert, auf den gezeigt wird, ist unveränderlich
int * const: Der Zeiger selbst ist unveränderlich und der Wert, auf den gezeigt wird, ist veränderlich
Beim Konvertieren von const int * -> int * const wird ein Fehler gemeldet
Konvertierung int * const -> const int * kann durchgeführt werden
Semantisch gesehen ist es einfacher zu verstehen, aber aus formaler Sicht haben beide eine unveränderliche Menge. Warum ist also bei der Konvertierung eine Richtung möglich, die andere jedoch nicht? Wenn ich darüber nachdenke, liegt es vielleicht daran, dass Hinweise und Werte nicht auf dem gleichen Niveau sind, aber ich weiß nicht, wie ich es klarstellen soll?
过去多啦不再A梦2017-05-16 13:33:16
假设这里讨论的是隐式转换(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的安全性,但是却因违背了其他某些条款而不能实现,那大概这语言药丸。滑稽