繁体   English   中英

实际上,const_cast的这种用法是否未定义?

[英]Is this usage of const_cast undefined in practice?

我有一个管理输入的类。 为了显示和更改键绑定,重要的是给调用者一个它可以拥有和更改的绑定的映射,然后再将其提交给管理器。 但是,只有管理员可以知道在此映射中可以插入/删除哪些内容的特定规则,因此必须强制呼叫者要求管理员进行更改。

调用者会获得地图的const版本,以确保它不能自行修改,而管理者仍然可以使用const_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
    }
}

当前这可以按预期工作,但是我对const_cast的使用感到担心,因为修改const变量原则上是UB(除非有例外?)

在实践中,这是否会导致UB或任何其他细微的性能问题或不同平台或编译器上的错误,或与可能的优化冲突?

在我看来,这有点像代码的味道 尽管可以正常工作,但现实是您已经声明了insertBindings方法来获取常量映射,但是您并未尊重该方法中的const-ness。

如果您可能要修改地图,则只需将类型声明为非常量即可,以便该方法以每个人期望的方式运行。

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。 其中,它可以在实践中失败的一种方式,是优化有权假设,因为fooconst -qualified在它的定义,那么它的非的价值点mutable数据成员不会改变。 因此, commitBindingscommitBindings代码commitBindings ,它可以重新排序对foo访问,以便在调用insertBinding导致其被修改之前读取数据成员。

在实践中,您的Map似乎并没有发生这种情况,但这是修改const限定对象的原因不仅仅是理论上的问题,而且是原因之一。

为了达到您想要的位置,您可以添加另一个级别的间接寻址(编译时间接寻址:编译器可以消除开销)。 定义一个具有Map的类作为私有数据成员,并且其唯一的公共mutator与insertBinding具有相同的作用。 这样,用户只能通过检查规则的代码来修改Map 为了提高效率,请确保您的类具有有效的move构造函数和move分配,因为复制std::multimap可能需要很多工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM