正在修改const声明对象上的可变对象的未定义行为

Is modifying a mutable on a const declared object undefined behavior?

本文关键字:对象 未定义 修改 const 声明      更新时间:2023-10-16

我有一个消息系统,我将一个结构体传递给不同的函数。在一个简明的示例中,消息是这样描述的:

struct Message {
    bool wasHandled;
    Message() {
        wasHandled = false;
    }
};

消息处理程序是这样调用的:

handleMessage(Message());

消息作为const引用传递。我这样做的主要动机是为了编写上面的一行代码。如果通过非const引用传递,我必须写:

Message message;
handleMessage(message);

句柄标志指示消息是否被函数处理。因此,handleMessage函数需要修改wasHandled标志。一个可能的实现是:

void handleMessage(const Message& message) {
    const_cast<bool&>(message.wasHandled) = true;
    // Do stuff here.
}

然而,根据我的理解,

handleMessage(Message());

等价于:(注意:这是不正确的,参见接受的答案)

const Message message;
handleMessage(message);

因此我改变了const对象的值。这是未定义行为。

将消息声明为

struct Message {
    mutable bool wasHandled;
    Message() {
        wasHandled = false;
    }
};

使其定义行为?这当然也会移除const强制转换。

注意,在这个特殊的例子中,wasHandle标志实际上永远不会被读取,如果调用者想知道它,则不能使用单行程序。然而,实际上并不是所有的呼叫者都对旗帜感兴趣。该消息也可能被分派到handleMessage内部使用该标志的其他函数。

你所拥有的太复杂了。首先,您对临时对象的理解是错误的。Message()是一个完全可变的值。它只是不能绑定到左值引用,因为它是右值。

如果你真的想处理可变左值和右值一样(这是不是其他一些设计问题的症状是有争议的),那么你应该简单地有两个函数重载:

void handleMessage(Message & m)  { handleImpl(m); }
void handleMessage(Message && m) { handleMessage(m); }