简体   繁体   English

const_cast和UB

[英]const_cast and UB

$5.2.11/7 - "[Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier68) may produce undefined behavior (7.1.5.1). ]" $ 5.2.11 / 7 - “[注意:根据对象的类型,通过指针,左值或指向数据成员的指针进行写入操作会导致const-qualifier68的const_cast) 可能会产生未定义的行为(7.1。 5.1)。]“

The wordings of this section (C++03) are surprising to me. 本节的措辞(C ++ 03)对我来说是令人惊讶的。 What is suprising are two things. 令人惊讶的是两件事。

a) Firstly, the use of 'may'. a)首先,使用'可能'。 Why is it 'may'? 为什么'可能'? Other places in the Standard are very definitive about the undefined behavior 标准中的其他地方对未定义的行为非常明确

b) Why is that the casting away the constness of a originally const object not straight away 'undefined behavior'. b)为什么抛弃原始const对象的常量而不是直接'未定义的行为'。 Why is it that a write is required for UB to be triggered? 为什么要触发UB需要写入?

a) Firstly, the use of 'may'. a)首先,使用'可能'。 Why is it 'may'? 为什么'可能'? Other places in the Standard are very definitive about the undefined behavior 标准中的其他地方对未定义的行为非常明确

Don't look too deeply into the use of the word may here. 不要太深入地使用这个词这里可以的。 The point is, casting away constness in this case causes undefined behavior. 关键是,在这种情况下抛弃constness会导致未定义的行为。

The C++ standard uses "may" or "might" often, as in: C ++标准经常使用“可能”或“可能”,如:

1.3.12: Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. 1.3.12:当本国际标准忽略了行为的任何明确定义的描述也可以预期不确定的行为。

Emphasis mine. 强调我的。 Basically, the standard uses the word "may" as in " is allowed to ". 基本上,标准使用“可以”一词,如“ 允许 ”。

b) Why is that the casting away the constness of a originally const object not straight away 'undefined behavior'. b)为什么抛弃原始const对象的常量而不是直接'未定义的行为'。 Why is it that a write is required for UB to be triggered? 为什么要触发UB需要写入?

A write triggers UB because it's possible that const objects can be stored in read-only memory on certain platforms. 写入触发UB,因为const对象可能存储在某些平台上的只读内存中。

My understanding is that it will only be UB if the object in question is fundamentally a const object rather than a const pointer or reference to an object which was not originally const. 我的理解是,如果所讨论的对象基本上是一个const对象而不是一个const指针或对一个最初不是const的对象的引用,它将只是UB。

The idea being that data that is fundamentally const could be loaded into a read-only portion of memory, and writing to that just isn't going to work. 这个想法是基本上是const的数据可以加载到内存的只读部分,而写入它只是不起作用。 However, it's guaranteed to work properly if the object in question is fundamentally mutable. 但是,如果有问题的对象基本上是可变的,那么它可以保证正常工作。

Ex: 例如:

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.

For a comment below, because code looks terrible in comments: 对于下面的评论,因为代码在评论中看起来很糟糕:

In §7.1.​5.1/4 of the standard, the example given is: 在标准的§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

So this is specifically allowed. 所以这是特别允许的。

For your first question, if something may produce undefined behavior, then that doesn't make it any less undefined. 对于你的第一个问题,如果某些东西可能会产生未定义的行为,那么这不会使它变得不那么明确。

For the second part, I'd imagine it is for interoperability reasons. 对于第二部分,我认为这是出于互操作性的原因。 For example, C doesn't (or didn't, before C99) have a const keyword, so if you want to pass a const object to a C function, the constness would have to be cast away. 例如,C不会(或者在C99之前没有)具有const关键字,因此如果要将const对象传递给C函数,则必须抛弃const。 So the C++ standard specifies that this is allowed as long as no writes are performed. 所以C ++标准规定只要不执行写操作就允许这样做。 If the C function is read-only, the constness can be safely cast away. 如果C函数是只读的,则可以安全地丢弃常量。

Even in C++, inconsistent or incomplete const-correctness is pretty common too. 即使在C ++中,不一致或不完整的const正确性也很常见。 So we do occasionally run into situations where we have to cast away const-ness in order to pass a const object to a function which doesn't modify its argument, but takes it by non-const. 所以我们偶尔会遇到这样的情况:为了将一个const对象传递给一个不修改其参数的函数,而是将它传递给非const,我们必须抛弃const。

I'd believe that is because a const object can be stored into read-only memory. 我相信这是因为const对象可以存储到只读内存中。 Thus, writing to it can have many various effects: program crash, segmentation fault, or no effect. 因此,写入它可能会产生许多不同的影响:程序崩溃,分段错误或无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM