在const声明的对象上修改一个mutable未定义的行为?

ras*_*mus 5 c++ undefined-behavior c++11

我有一个消息系统,我将结构传递给不同的函数.在一个精简的例子中,消息描述如下:

struct Message {
    bool wasHandled;

    Message() {
        wasHandled = false;
    }
};
Run Code Online (Sandbox Code Playgroud)

并调用消息处理程序,如下所示:

handleMessage(Message());
Run Code Online (Sandbox Code Playgroud)

消息作为const引用传递.我的主要动机是,我可以写上面的单行.如果通过非const引用传递,我将不得不写:

Message message;
handleMessage(message);
Run Code Online (Sandbox Code Playgroud)

handle标志指示消息是否由函数处理.handleMessage因此该功能需要修改wasHandled标志.一种可能的实现方式是:

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

但是,根据我的理解,

handleMessage(Message());
Run Code Online (Sandbox Code Playgroud)

相当于:( 注意:这是不正确的,请参阅接受的答案)

const Message message;
handleMessage(message);
Run Code Online (Sandbox Code Playgroud)

因此我正在改变const对象的值.这是未定义的行为.

将该消息声明为

struct Message {
    mutable bool wasHandled;

    Message() {
        wasHandled = false;
    }
};
Run Code Online (Sandbox Code Playgroud)

让它定义行为?这当然也会删除const cast.

请注意,在此特定示例中,wasHandle标志实际上从未被读取,并且如果调用者想要知道它,则不能使用单行.但是,实际上并非所有来电者都对旗帜感兴趣.消息也可能被分派到handleMessage使用该标志的其他函数内部.

Ker*_* SB 4

你所拥有的过于复杂。首先,您对临时对象的理解是错误的。Message()是一个完全可变的值。只是由于它是右值,因此无法绑定到左值引用。

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

void handleMessage(Message & m)  { handleImpl(m); }
void handleMessage(Message && m) { handleMessage(m); }
Run Code Online (Sandbox Code Playgroud)