const_cast和ub
-
27-09-2019 - |
题
$ 5.2.11/7-“ [注意:取决于对象的类型,通过指针,lvalue或指针的写入操作,由const_cast产生的数据构件,该const_cast将const -qualifier 68铸造出来) 可能 产生不确定的行为(7.1.5.1)。 ]”
本节的措辞(C ++ 03)令我惊讶。令人惊讶的是两件事。
a)首先,使用“可能”。为什么“可能”?标准中的其他地方对不确定的行为非常确定
b)为什么要铸造最初的const对象的构成,而不是立即“不确定的行为”。为什么要触发UB需要写作?
解决方案
a)首先,使用“可能”。为什么“可能”?标准中的其他地方对不确定的行为非常确定
不要太深入地看待单词的使用 可能 这里。关键是,在这种情况下,抛弃构成会导致不确定的行为。
C ++标准使用“可能”或“可能”,例如:
1.3.12:未定义的行为 可能 当该国际标准省略对行为的任何明确定义的描述时,也可以预期。
强调我的。基本上,该标准使用“ May”一词如“被允许".
b)为什么要铸造最初的const对象的构成,而不是立即“不确定的行为”。为什么要触发UB需要写作?
写入触发UB,因为const对象可能可以存储在某些平台上的只读内存中。
其他提示
我的理解是,只有当所讨论的对象从根本上是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
因此,这是特别允许的。
对于您的第一个问题,是否有什么 可能 产生不确定的行为,那么这并不能使它变得不那么明确。
对于第二部分,我想这是出于互操作性的原因。例如,C没有(或没有,在C99之前)有一个 const
关键字,因此,如果要将const对象传递给C函数,则必须将constness抛弃。因此,C ++标准指定只要执行任何写作,就可以使用此标准。如果C函数仅读取,则可以安全地抛弃constness。
即使在C ++中,不一致或不完整的const-Correct也很常见。因此,我们偶尔会遇到必须抛弃const-ness的情况,才能将const对象传递给不修改其参数但通过非const的函数。
我相信那是因为 const
对象可以存储到仅读取的内存中。因此,写信给它可能会产生许多不同的效果:程序崩溃,分割故障或无效。