是否将指针转换为const指针并转换回未定义的原始类型?

时间:2019-03-30 04:34:48

标签: c++ language-lawyer undefined-behavior const-cast

我知道将const指针强制转换为非const类型可能是未定义的行为,但是如果该指针最初不是const怎么办?

int i = 0;
int * pi = &i;
const int * const_pi = const_cast<const int*>(pi);
int * non_const_pi = const_cast<int*>(const_pi);
*non_const_pi = 0;
*non_const_pi = 1;
int j = *non_const_pi;

是否存在未定义的行为?如果有的话,它们在哪里发生?编译器是否可以假设non_const_pi是从const指针强制转换的,并且不执行任何修改?

2 个答案:

答案 0 :(得分:5)

  

我知道将const指针转换为非const类型可能是未定义的行为。

那是个误会。

常量广播指针绝不会导致未定义的行为。取消引用通过const-将const_cast指针指向const对象而获得的非const指针,即使原始对象用于读取,唯一模式。如果尝试写入对象,则为未定义行为。

int const i = 10;
int const* p1 = &i;
int* p2 = const_cast<int*>(p1);  // OK.
std::cout << *p2;                // Still OK.
*p2 = 20;                        // Not OK.

鉴于此,您的第二段代码完全可以。由于原始对象是非const对象,因此没有未定义的行为。

来自The Standard, Section 5.2.11, Expressions/Const cast

  

指针const_cast的结果引用原始对象。

答案 1 :(得分:4)

不,这不是UB。仅当尝试通过非常量访问路径修改const对象时,才会导致UB。对于这种情况,实际上non_const_pi指向非常量对象i,然后对其进行修改就可以了。

标准[dcl.type.cv]/4中有一个确切的例子:

  

...任何修改尝试([expr.ass],[expr.post.incr],   [expr.pre.incr])常量对象([basic.type.qualifier])   寿命([basic.life])导致不确定的行为。 [示例:

...

int i = 2;                              // not cv-qualified
const int* cip;                         // pointer to const int
cip = &i;                               // OK: cv-qualified access path to unqualified
*cip = 4;                               // ill-formed: attempt to modify through ptr to const

int* ip;
ip = const_cast<int*>(cip);             // cast needed to convert const int* to int*
*ip = 4;                                // defined: *ip points to i, a non-const object