[英]boost::any_cast(const any&) uses const_cast<> — Isn't this potentially UB?
[英]const_cast and UB
$ 5.2.11 / 7 - “[注意:根据对象的类型,通过指针,左值或指向数据成员的指针进行写入操作会导致const-qualifier68的const_cast) 可能会产生未定义的行为(7.1。 5.1)。]“
本节的措辞(C ++ 03)对我来说是令人惊讶的。 令人惊讶的是两件事。
a)首先,使用'可能'。 为什么'可能'? 标准中的其他地方对未定义的行为非常明确
b)为什么抛弃原始const对象的常量而不是直接'未定义的行为'。 为什么要触发UB需要写入?
a)首先,使用'可能'。 为什么'可能'? 标准中的其他地方对未定义的行为非常明确
不要太深入地使用这个词在这里可以的。 关键是,在这种情况下抛弃constness会导致未定义的行为。
C ++标准经常使用“可能”或“可能”,如:
1.3.12:当本国际标准忽略了行为的任何明确定义的描述也可以预期不确定的行为。
强调我的。 基本上,标准使用“可以”一词,如“ 允许 ”。
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函数,则必须抛弃const。 所以C ++标准规定只要不执行写操作就允许这样做。 如果C函数是只读的,则可以安全地丢弃常量。
即使在C ++中,不一致或不完整的const正确性也很常见。 所以我们偶尔会遇到这样的情况:为了将一个const对象传递给一个不修改其参数的函数,而是将它传递给非const,我们必须抛弃const。
我相信这是因为const
对象可以存储到只读内存中。 因此,写入它可能会产生许多不同的影响:程序崩溃,分段错误或无效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.