正在修改const声明对象上的可变对象的未定义行为
Is modifying a mutable on a const declared object undefined behavior?
我有一个消息系统,我将一个结构体传递给不同的函数。在一个简明的示例中,消息是这样描述的:
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); }
相关文章:
- 在销毁期间从另一个线程调用对象上调用方法是否未定义行为?
- 为什么销毁被放置 new 覆盖的对象不是未定义的行为?
- 未定义的对象(〔basic.life〕/8):为什么允许引用重新绑定(和常量修改)
- 正在通过const-ref未定义的行为捕获新构造的对象
- 仅标头类 + 仅当返回该类的对象时,对函数的未定义引用
- 如果用户尝试从 JS 调用对象的未定义函数C++则回调C++代码
- C++:在共享对象中调用抽象基类构造函数/未定义的符号
- Cython:共享对象中未定义的符号
- 对"车辆的 vtable"的未定义引用 - 面向对象的编程练习
- 为什么内置类型的对象上的溢出会导致异常/未定义的行为?
- 正在加载共享对象:文件中未定义版本Qt_5
- 对象文件中的未定义引用 - 如何查找哪个库包含它
- static_cast实际上不是对象类型的类型是未定义的行为吗?
- 尝试与从 CUDA 对象构建的共享库链接时未定义的符号
- C++ / G++ Maxmind geolite2++ 第三方共享对象未定义引用
- 对象在函数中未定义
- C++ 未定义的对象引用
- 通过在此指针上放置新位置重新初始化对象时未定义的行为
- 无法加载共享对象:未定义的符号
- 模板和静态对象(未定义的引用和必需的引用)