gpt4 book ai didi

c++ - 为什么在丢弃指向该对象的指针的常量之后写入一个非常量对象而不是 UB?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:14:53 27 4
gpt4 key购买 nike

根据 C++ 标准,如果对象本身不是 const,则可以从指针中丢弃 const 并写入对象。这样:

 const Type* object = new Type();
const_cast<Type*>( object )->Modify();

没关系,但是这个:

 const Type object;
const_cast<Type*>( &object )->Modify();

是 UB。

The reasoning is当对象本身是 const 时,允许编译器优化对其的访问,例如,不执行重复读取,因为重复读取对未更改的对象没有意义。

问题是编译器如何知道哪些对象实际上是 const?比如我有一个函数:

void function( const Type* object )
{
const_cast<Type*>( object )->Modify();
}

它被编译成一个静态库,编译器不知道它会被哪些对象调用。

现在调用代码可以这样做:

Type* object = new Type();
function( object );

它会很好,或者它可以这样做:

const Type object;
function( &object );

这将是未定义的行为。

编译器应该如何遵守这些要求?不让后者发挥作用,如何让前者发挥作用?

最佳答案

当您说“如何在不使后者起作用的情况下使前者起作用?”一个实现只需要让前者工作,它不需要 - 除非它想帮助程序员 - 做出任何额外的努力来试图让后者以某种特定方式工作。 未定义的行为为实现提供了自由,而不是义务。

举个更具体的例子。在此示例中,在 f() 中,编译器可能会在调用 EvilMutate 之前将返回值设置为 10,因为 cobj.member 是 const一旦 cobj 的构造函数完成并且随后可能不会被写入。它不能在 g() 中做出相同的假设,即使只调用了一个 const 函数。如果 EvilMutatef() 中调用 cobj 时试图改变 member 未定义的行为 发生并且实现不需要使任何后续操作具有任何特定效果。

编译器假设一个真正的 const 对象不会改变的能力受到保护,因为这样做会导致未定义的行为;事实上,它不会对编译器施加额外的要求,只会对程序员施加额外的要求。

struct Type {
int member;
void Mutate();
void EvilMutate() const;
Type() : member(10) {}
};


int f()
{
const Type cobj;
cobj.EvilMutate();
return cobj.member;
}

int g()
{
Type obj;
obj.EvilMutate();
return obj.member;
}

关于c++ - 为什么在丢弃指向该对象的指针的常量之后写入一个非常量对象而不是 UB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8530611/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com