const_cast和UB

时间:2010-10-28 11:55:17

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

  

$ 5.2.11 / 7 - “[注:取决于   对象的类型,写操作   通过指针,左值或指针   由a产生的数据成员   const_cast抛弃了一个   const-qualifier68)可能生成   未定义的行为(7.1.5.1)。 ]“

本节的措辞(C ++ 03)让我感到惊讶。令人惊讶的是两件事。

a)首先,使用'可能'。为什么'可能'?标准中的其他地方对未定义的行为非常明确

b)为什么抛弃原始const对象的常量而不是直接'未定义的行为'。为什么要触发UB需要写入?

4 个答案:

答案 0 :(得分:4)

  

a)首先,使用'可能'。为什么是   有可能'?标准中的其他地方   非常明确的   未定义的行为

不要过分深入研究 may 这个词的用法。关键是,在这种情况下抛弃constness会导致未定义的行为。

C ++标准经常使用“可能”或“可能”,如:

  

1.3.12:本国际时也可以预期未定义的行为   标准省略了任何描述   行为的明确定义。

强调我的。基本上,该标准使用“可能”一词,如“is allowed to”。

  

b)为什么抛弃了   原始const对象的constness   不是直接'未定义   行为'。为什么写是   是否需要触发UB?

写入触发UB,因为const对象可能存储在某些平台的只读内存中。

答案 1 :(得分:3)

我的理解是,如果有问题的对象基本上是一个const对象而不是一个const指针或对一个最初不是const的对象的引用,它将只是UB。

这个想法是基本上const的数据可以加载到内存的只读部分,而写入它只是不起作用。但是,如果有问题的对象基本上是可变的,那么它可以保证正常工作。

例如:

const int  x = 4;
const int *y = x;

*const_cast<int*>(x) = 3; // UB - the pointed-to object may 
                          // be in read-only memory or whatever.

int        a = 7;
const int *b = a;

*const_cast<int*>(b) = 6; // Not UB - the pointed-to object is 
                          // fundamentally mutable.

对于下面的评论,因为代码在评论中看起来很糟糕:

在标准的§7.1.5.1/ 4中,给出的例子是:

int i = 2;
const int * cip; // pointer to const int
cip = &i;        // OK: cv-qualified access path to unqualified
...
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

所以这是特别允许的。

答案 2 :(得分:3)

对于您的第一个问题,如果某些可能产生未定义的行为,那么这不会使其变得不那么明确。

对于第二部分,我认为这是出于互操作性的原因。例如,C不会(或者在C99之前没有)具有const关键字,因此如果要将const对象传递给C函数,则必须抛弃常量。所以C ++标准规定只要不执行写操作就允许这样做。如果C函数是只读的,则可以安全地抛弃常量。

即使在C ++中,不一致或不完整的const正确性也很常见。因此,我们偶尔会遇到这样的情况,即我们必须抛弃const,以便将const对象传递给不修改其参数的函数,但是将它取为非const。

答案 3 :(得分:1)

我认为这是因为const对象可以存储到只读内存中。因此,写入它可能会产生许多不同的影响:程序崩溃,分段错误或无效。