如何在具有非const指针键的映射中通过const指针键查找

时间:2019-02-08 08:17:16

标签: c++ stl const-correctness const-cast const-pointer

以下C ++代码无法编译,因为它将非常量指针传递给需要常量指针的created_at函数。

UPDATE node_status AS s SET s.updated_at = (
    SELECT created_at
    FROM node_status
    WHERE id > s.id AND node_id = s.node_id
    LIMIT 1
)
WHERE s.node_id = 1811

有没有办法在不更改地图类型或使变量find()为非常量的情况下使查找工作生效? 在所有功能#include <map> std::map<int*, double> mymap; double myfind(const int * mykey) { return mymap.find(mykey)->second; } 不修改指向的对象之后,它仅比较指针。

4 个答案:

答案 0 :(得分:1)

映射中的键在语义上是不可变的,所有允许直接访问键的映射操作都是通过const限定键类型来实现的(例如,value_type被定义为pair<const Key, T>

在使用int*键类型的情况下,您会得到一个指向非常量constint)的int*const指针,这不是很好(仍然有效,因为仅将指针 value 用作键,但是不变性的语义被淡化了,这可能导致错误。)

只需放弃将map更改为map<const int*, double>即可,而不是放弃常数。

然后它将适用于const int*int*键。

#include <map>

std::map<const int*, double> mymap;

double myfind(const int * mykey)
{
    return mymap.find(mykey)->second; // just works
}

double myfind(int * mykey)
{
    return mymap.find(mykey)->second; // also works
}

答案 1 :(得分:0)

尝试使用const_cast,它可以更改变量的恒定性(或易变性)。

#include <map>

std::map<int*, double> mymap;

double myfind(const int * mykey)
{
    return mymap.find(const_cast<int*>(mykey))->second;
}

答案 2 :(得分:0)

我想我已经找到了解决方案,但是它需要C ++ 14透明比较器。

#include <map>
#include <iostream>

struct CompareIntPtrs
{
    using is_transparent = void; // enabling C++14 transparent comparators

    bool operator()(const int * l, const int * r) const
    {
        return l < r;
    }
};

std::map<int*, double, CompareIntPtrs> mymap;

double myfind(const int * key)
{
    return mymap.find(key)->second;
}

int main()
{
    int x {6};
    mymap[&x] = 66; // inserting to the map
    const int * px = &x; // creating a "const int *" variable

    std::cout << myfind(px) << std::endl; // using "const int *" for finding in map with "int*" keys
    std::cout << mymap.find(px)->second << std::endl; // we could even skip using myfind()
}

here是有关C ++ 14透明比较器的出色文章。 老实说,通过添加比较器,mymap的类型发生了一些变化,这本来是我本来不想做的,但这是我能找到的最佳解决方案。

如果C ++ 14不可用,我们至少可以选择两种弊端。 第一个方法是将mymap复制到std::map<const int*, double>中的新myfind上,这效率极低。 第二个方法是使用const_cast<int*>(mykey)(如果可能应为avoided)来消除常数。

答案 3 :(得分:-1)

您可能遇到常量正确性问题。 const int * may not be what you think it is。它是常数整数的指针。这与地图的键类型不同,键的类型是指向(非恒定)整数的指针。而且两者都与int * const相同,std::map<int *, double> mymap; double myfind(int * const mykey) { return mymap.find(mykey)->second; } 是指向(非恒定)整数的恒定指针。问题不在于键值本身是可变的还是不可变的,而是存储指针的对象是可变的还是不可变的。

例如,它将编译:

std::map<const int *, double> mymap;
double myfind(const int *mykey) {
    return mymap.find(mykey)->second;
}
double myfind2(const int * const mykey) {
    return mymap.find(mykey)->second;
}

这样做:

const int *

您看到区别了吗?在您的原始代码中,编译器非常正确地标记错误。如果您的函数采用int,则实际上是在保证不要修改我传入的指针所指向的int *。但是,如果在函数中使用std::map这样的指针, int的密钥,您可能允许某人修改std::map::find()

在这种特殊情况下,我们知道const_cast<>不会分配给指针参数,但是编译器不会赋值,这就是apiResponse = JsonConvert.DeserializeObject<List<Email>>(response.Content); 存在的原因,如其他答案所指出的。