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
引用?那只是个谎言!“在实践中”意味着什么