C++ const_cast的这种用法在实践中是否没有定义?
我有一个管理输入的类。要显示和更改键绑定,在将其提交给管理器之前,为调用方提供一个可以拥有和更改的绑定映射非常重要。但是,关于在此映射中可以插入/删除哪些内容,有一些特定的规则只有经理知道,因此必须强制调用方要求经理进行更改 调用者获得映射的C++ const_cast的这种用法在实践中是否没有定义?,c++,constants,C++,Constants,我有一个管理输入的类。要显示和更改键绑定,在将其提交给管理器之前,为调用方提供一个可以拥有和更改的绑定映射非常重要。但是,关于在此映射中可以插入/删除哪些内容,有一些特定的规则只有经理知道,因此必须强制调用方要求经理进行更改 调用者获得映射的const版本,以确保它不能自己修改映射,而管理员仍然可以使用const\u cast typedef std::multimap<Key, Input> Map; class InputManager{ public: co
const
版本,以确保它不能自己修改映射,而管理员仍然可以使用const\u cast
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
}
}
typedef std::multimap映射;
类输入管理器{
公众:
常量映射getBindings(){
//构建地图并返回它
}
bool insertBinding(常量映射和绑定、键、输入){
//首先检查多个规则后执行插入
if(规则sallowit){
const_cast(bindings).insert(std::make_pair(key,input));
返回true;
}否则{
返回false;
}
}
无效提交绑定(常量映射和绑定){
//提交绑定以替换旧的
}
}
目前这项工作与预期的一样,但我担心使用const\u cast
,因为修改const
变量在原则上是UB(除非有例外?)
在实践中,这会导致UB或其他任何微妙的性能问题或不同平台或编译器上的bug,或与可能的优化冲突吗?在我看来,这有点像一个错误。尽管它会起作用,但事实是您已经声明了
insertBindings
方法来获取一个常量映射,但您并不尊重该方法中的常量
如果您打算修改映射,那么只需将该类型声明为非常量,以便该方法以每个人都期望的方式运行。在我看来,这有点像一个简单的方法。尽管它会起作用,但事实是您已经声明了
insertBindings
方法来获取一个常量映射,但您并不尊重该方法中的常量
如果您打算修改映射,那么只需将该类型声明为非常量,以便该方法以每个人都期望的方式运行。
const map getBindings()
是一种毫无意义的返回类型。用户在任何情况下都可以编写以下代码:
Map foo = manager.getBindings();
manager.insertBinding(foo, key, whatever);
foo.clear();
manager.commitBindings(foo);
在这种情况下,代码已经定义了行为(至少,commitBindings
可能不希望看到空映射)。或者,他们可以这样写:
const Map foo = manager.getBindings();
manager.insertBinding(foo, key, whatever);
manager.commitBindings(foo);
在这种情况下,代码根据标准具有UB。它在实践中可能失败的一种方式是,优化器有权假设由于foo
在其定义点处是const
-限定的,因此其非可变
数据成员的值不会改变。因此,在内联commitBindings
的代码之后,它可以重新排序对foo
的访问,以便在调用insertBinding
之前读取数据成员,从而导致对其进行修改
在实践中,这似乎不会发生在您的映射上,但这是为什么修改常量限定对象可能不仅仅是一个理论问题的原因之一
为了达到您想要的目的,您可以添加另一个级别的间接寻址(编译时间接寻址:编译器可以消除开销)。定义一个类,该类具有映射
作为私有数据成员,并且其唯一的公共mutator与插入绑定
具有相同的效果。然后,用户除了通过检查规则的代码之外,没有办法修改地图
。为了提高效率,请确保您的类具有有效的移动构造函数和移动赋值,因为复制std::multimap
可能需要大量工作。const-Map-getBindings()
是一种相当无意义的返回类型。用户在任何情况下都可以编写以下代码:
Map foo = manager.getBindings();
manager.insertBinding(foo, key, whatever);
foo.clear();
manager.commitBindings(foo);
在这种情况下,代码已经定义了行为(至少,commitBindings
可能不希望看到空映射)。或者,他们可以这样写:
const Map foo = manager.getBindings();
manager.insertBinding(foo, key, whatever);
manager.commitBindings(foo);
在这种情况下,代码根据标准具有UB。它在实践中可能失败的一种方式是,优化器有权假设由于foo
在其定义点处是const
-限定的,因此其非可变
数据成员的值不会改变。因此,在内联commitBindings
的代码之后,它可以重新排序对foo
的访问,以便在调用insertBinding
之前读取数据成员,从而导致对其进行修改
在实践中,这似乎不会发生在您的映射上,但这是为什么修改常量限定对象可能不仅仅是一个理论问题的原因之一
为了达到您想要的目的,您可以添加另一个级别的间接寻址(编译时间接寻址:编译器可以消除开销)。定义一个类,该类具有映射
作为私有数据成员,并且其唯一的公共mutator与插入绑定
具有相同的效果。然后,用户除了通过检查规则的代码之外,没有办法修改地图
。为了提高效率,请确保您的类具有有效的移动构造函数和移动分配,因为复制std::multimap
可能需要大量工作。为什么管理器不存储映射本身?这将解决您的所有问题。是否在const
中传递映射?对“UB或not”问题的回答取决于对象的constness绑定
。您发布的代码不清楚。不清楚调用中将使用哪个对象作为参数。如果要更改它,为什么要使用const
引用?那只是个谎言!“在实践中”意味着什么