- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个管理输入的类。要显示和更改键绑定(bind),重要的是在完成后将其提交给管理器之前,为调用者提供它可以拥有和更改的绑定(bind)的映射。但是,这个映射中可以插入/删除什么的具体规则只有管理者知道,因此调用者必须强制要求管理者进行更改。
调用者获取 map 的 const
版本以确保它不能自行修改它,而管理器仍然可以使用 const_cast
更改 map
typedef std::multimap<Key, Input> Map;
class InputManager{
public:
const Map getBindings(){
// builds the map and returns it
}
bool insertBinding(const Map & bindings, Key key, Input input){
// performs the insert after checking several rules first
if(rulesAllowIt){
const_cast<Map&>(bindings).insert(std::make_pair(key, input));
return true;
}else{
return false;
}
}
void commitBindings(const Map & bindings){
// commits the bindings to replace the old
}
}
这目前按预期工作,但我担心 const_cast
的使用,因为修改 const
变量原则上是 UB(除非有异常(exception)?)
在实践中,这会导致 UB 或任何其他微妙的性能问题或不同平台或编译器上的错误,或者与可能的优化冲突吗?
最佳答案
const Map getBindings()
是一个毫无意义的返回类型。用户可以在任何情况下编写代码:
Map foo = manager.getBindings();
manager.insertBinding(foo, key, whatever);
foo.clear();
manager.commitBindings(foo);
在这种情况下,代码已经定义了行为(至少,直到 commitBindings
可能不希望看到一个空 map )。或者他们可以这样写:
const Map foo = manager.getBindings();
manager.insertBinding(foo, key, whatever);
manager.commitBindings(foo);
在这种情况下,代码具有符合标准的 UB。 在实践中它可能会失败的一种方式是,优化器有权假设因为 foo
是 const
-qualified它被定义,那么它的非可变
数据成员的值将不会改变。因此,在内联 commitBindings
的代码后,它可以重新排序对 foo
的访问,以便在 调用 之前读取数据成员 insertBinding
导致它被修改。
在实践中,这似乎并没有发生在您的 Map
上,但这是为什么修改 const
限定的对象不仅仅是一个理论问题的原因之一.
要到达您想要的位置,您可以添加另一层间接(编译时间接:编译器可以消除开销)。定义一个类,该类将 Map
作为私有(private)数据成员,并且其唯一的公共(public)修改器与 insertBinding
具有相同的效果。那么除了通过检查规则的代码之外,用户无法修改 Map
。为了提高效率,请确保您的类具有有效的移动构造函数和移动赋值,因为复制 std::multimap
可能需要大量工作。
关于c++ - const_cast 的这种用法在实践中是否未定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37075913/
我通常不会这样做,但我目前正在从事的项目需要几个位于 c 源文件中的函数。 extern "C" { int words(char sentence[]); int match(cha
我是一名优秀的程序员,十分优秀!