以下C ++代码不编译,因为它通过一个非const指针,该期望一个const指针find()
功能。
#include <map>
std::map<int*, double> mymap;
double myfind(const int * mykey)
{
return mymap.find(mykey)->second;
}
有没有办法如何使找工作,而不改变地图的类型或制造变量mykey
非const?所有find()
不修改尖锐的物体功能后,它只是比较指针。
地图中的一个关键是语义上不可变的,所有映射操作,允许键直接访问做到这一点的const
-资格密钥类型(例如value_type
被定义为pair<const Key, T>
)。
在int*
密钥类型的情况下,但是你会得到一个const
指向非const int
(int*const
),这是不是很漂亮的(它仍然有效,因为只有指针值作为重点,而是永恒的语义被稀释,这可能会导致错误)。
相反虚掷常量性的,只是改变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
}
尝试const_cast
它允许你改变变量的常量性(或波动)。
#include <map>
std::map<int*, double> mymap;
double myfind(const int * mykey)
{
return mymap.find(const_cast<int*>(mykey))->second;
}
我想我已经找到了解决办法,但它需要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()
}
优异的文章关于C ++ 14透明比较可以发现here。要完全诚实的,通过添加比较,mymap
类型略有改变,我本来不想来,但它是我能找到的最好的解决方案。
如果C ++ 14不可用,至少有两两害相权,我们可以选择。第一个是mymap
复制到std::map<const int*, double>
新myfind
,这是可怕的效率不高。第二个是通过使用应const_cast<int*>(mykey)
如果可能的话avoided铸造远常量性。
你可能有一个const,正确性问题。 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<>
存在在其他的答案中指出。