c++ - const_cast 的这种用法在实践中是否未定义?

标签 c++ constants

我有一个管理输入的类。要显示和更改键绑定(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。 在实践中它可能会失败的一种方式是,优化器有权假设因为 fooconst-qualified它被定义,那么它的非可变数据成员的值将不会改变。因此,在内联 commitBindings 的代码后,它可以重新排序对 foo 的访问,以便在 调用 之前读取数据成员 insertBinding 导致它被修改。

在实践中,这似乎并没有发生在您的 Map 上,但这是为什么修改 const 限定的对象不仅仅是一个理论问题的原因之一.

要到达您想要的位置,您可以添加另一层间接(编译时间接:编译器可以消除开销)。定义一个类,该类将 Map 作为私有(private)数据成员,并且其唯一的公共(public)修改器与 insertBinding 具有相同的效果。那么除了通过检查规则的代码之外,用户无法修改 Map。为了提高效率,请确保您的类具有有效的移动构造函数和移动赋值,因为复制 std::multimap 可能需要大量工作。

关于c++ - const_cast 的这种用法在实践中是否未定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37075913/

相关文章:

模板中的 C++ 函数指针

C++ 翻译成 objective-C

objective-c - 某种外部变量与静态变量之间的区别

c++ - 什么是三法则?

c++ - 优化稀疏矩阵中的对数熵计算

c++ - 为什么将字符串文字传递给 char* 参数有时只是编译器错误?

c++ - 指向常量的指针

python - Scipy 基于误差平方和优化常数

c++ - 使用第三方库 (sbpl)

c++ - 在 Linux 上为 OpenGL 4.2 设置开发环境(无法获取 gl.h)