我有一个消息系统,我将结构传递给不同的函数。在一个精简的例子中,消息描述如下:
struct Message {
bool wasHandled;
Message() {
wasHandled = false;
}
};
并且像这样调用消息处理程序:
handleMessage(Message());
消息作为const引用传递。我的主要动机是,我可以写上面的单行。如果通过非const引用传递,我将不得不写:
Message message;
handleMessage(message);
handle标志指示消息是否由函数处理。因此函数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 cast。
请注意,在此特定示例中,wasHandle
标志实际上从未被读取,并且如果调用者想知道它,则不能使用单行。但是,实际上并非所有来电者都对旗帜感兴趣。该消息也可能被调度到handleMessage
内使用该标志的其他函数。
答案 0 :(得分:4)
你所拥有的是过于复杂。首先,您对临时对象的理解是错误的。 Message()
是一个完全可变的值。它只是因为是一个右值而无法绑定到左值引用。
如果你真的想要处理可变的左值和右值(并且它是否是一些其他设计问题的症状,这是有争议的),那么你应该只有两个函数重载:
void handleMessage(Message & m) { handleImpl(m); }
void handleMessage(Message && m) { handleMessage(m); }