std::map 的 const_cast 问题

发布于 2024-11-02 22:44:47 字数 1262 浏览 1 评论 0原文

我最近遇到了一个问题,我能想到的避免它的唯一方法是使用 const_cast - 但我猜测有一种我没有想到的方法可以避免这种情况,而无需更改代码的功能。下面的代码片段将我的问题提炼成一个非常简单的示例。

struct Nu
{
    Nu() {v = rand();}
    int v;
};

struct G
{
    ~G()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) delete it->first;
    }
    void AddNewNu()
    {
        _m[new Nu] = 0.5f;
    }
    void ModifyAllNu()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) it->first->v++;
    }
    float F(const Nu *n) const
    {
        auto it = _m.find(n);
        // maybe do other stuff with it
        return it->second;
    }

    map<Nu*, float> _m;
};

在这里,假设 Nu 实际上是一个非常大的结构,其布局已经通过匹配外部库的需要而固定(因此“浮动”不能简单地折叠到 Nu 中,并且由于各种其他原因它不能 <代码>地图)。 G 结构有一个映射,用于保存它创建的所有 Nu(并最终在销毁时将它们全部删除)。正如所写,函数 F 将无法编译 - 它无法按照 std::map 的预期将 (const Nu *n) 强制转换为 (Nu n)。但是map不能切换为map,因为一些非常量函数仍然需要修改Nu内部的_m。当然,我也可以将所有这些 Nu 存储在另一个 std::vector 中,然后将映射类型切换为 const - 但这引入了一个完全不必要的向量。因此,我目前想到的唯一替代方案是在 F 函数内使用 const_cast (这应该是安全的 const_cast),我想知道这是否可以避免。

经过一番寻找之后,这个完全相同的问题已经在这里得到解决: Calling map::find带有 const 参数

I recently hit a problem and the only way I can see to avoid it is to use const_cast - but I'm guessing there is a way I'm not thinking of to avoid this without otherwise changing the function of the code. The code snippet below distills my problem into a very simple example.

struct Nu
{
    Nu() {v = rand();}
    int v;
};

struct G
{
    ~G()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) delete it->first;
    }
    void AddNewNu()
    {
        _m[new Nu] = 0.5f;
    }
    void ModifyAllNu()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) it->first->v++;
    }
    float F(const Nu *n) const
    {
        auto it = _m.find(n);
        // maybe do other stuff with it
        return it->second;
    }

    map<Nu*, float> _m;
};

Here, suppose Nu is actually a very large struct whose layout is already fixed by the need to match an external library (and thus the "float" can't simply be folded into Nu, and for various other reasons it can't be map<Nu, float>). The G struct has a map that it uses to hold all the Nu's it creates (and ultimately to delete them all on destruction). As written, the function F will not compile - it cannot cast (const Nu *n) to (Nu n) as expected by std::map. However, the map can't be switched to map<const Nu*, float> because some non-const functions still need to modify the Nu's inside _m. Of course, I could alternatively store all these Nu's in an additional std::vector and then switch the map type to be const - but this introduces a vector that should be entirely unnecessary. So the only alternative I've thought of at the moment is to use const_cast inside the F function (which should be a safe const_cast) and I'm wondering if this is avoidable.

After a bit more hunting this exact same problem has already been addressed here: Calling map::find with a const argument

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

可是我不能没有你 2024-11-09 22:44:47

这是因为 map 需要 Nu* const,但您给了它一个 const Nu*。我也觉得这很不合逻辑,也不明白为什么,但事实就是这样。

This is because the map expects Nu* const, but you have given it a const Nu*. I also find it highly illogical and don't understand why, but this is how it is.

眼中杀气 2024-11-09 22:44:47

在你的情况下“find”将返回一个const_iterator。推杆:

map<Nu*,float>::const_iterator it = _m.find(n);

...

return it->second;

我认为应该有效。

由于您处于 const 方法中,因此您当然只能读取地图,而不能写入/修改它

"find" in your case will return a const_iterator. putting:

map<Nu*,float>::const_iterator it = _m.find(n);

...

return it->second;

should work I think.

Since you are in a const method you can only read your map of course, not write/modify it

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文