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

时间:2014-07-26 07:33:06

标签: c++ c++11 undefined-behavior

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

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内使用该标志的其他函数。

1 个答案:

答案 0 :(得分:4)

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

如果你真的想要处理可变的左值和右值(并且它是否是一些其他设计问题的症状,这是有争议的),那么你应该只有两个函数重载:

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