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使用该标志的其他函数内部.
你所拥有的过于复杂。首先,您对临时对象的理解是错误的。Message()是一个完全可变的值。只是由于它是右值,因此无法绑定到左值引用。
如果您确实想处理可变的左值和右值(这是否是其他一些设计问题的症状,这是有争议的),那么您应该简单地有两个函数重载:
void handleMessage(Message & m) { handleImpl(m); }
void handleMessage(Message && m) { handleMessage(m); }
Run Code Online (Sandbox Code Playgroud)