以下 C++ 代码无法编译,因为它将非常量指针传递给find()
需要 const 指针的函数。
#include <map>
std::map<int*, double> mymap;
double myfind(const int * mykey)
{
return mymap.find(mykey)->second;
}
有没有办法在不改变地图类型或使变量mykey
非常量的情况下进行查找工作?毕竟函数find()
没有修改指向的对象,它只是比较指针。
以下 C++ 代码无法编译,因为它将非常量指针传递给find()
需要 const 指针的函数。
#include <map>
std::map<int*, double> mymap;
double myfind(const int * mykey)
{
return mymap.find(mykey)->second;
}
有没有办法在不改变地图类型或使变量mykey
非常量的情况下进行查找工作?毕竟函数find()
没有修改指向的对象,它只是比较指针。
映射中的键在语义上是不可变的,所有允许直接访问键的映射操作都是通过const
- 限定键类型(例如value_type
定义为pair<const Key, T>
)来实现的。
但是,在键类型的情况下,int*
您会得到一个const
指向非 const int
( int*const
) 的指针,这不是很好(它仍然有效,因为只有指针值用作键,但是不变性的语义被稀释了,这可能导致错误)。
与其抛弃 constness,不如将其更改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 透明比较器的优秀文章。老实说,通过添加比较器,mymap
我原本不想的类型略有改变,但这是我能找到的最佳解决方案。
如果 C++14 不可用,我们至少可以选择两个弊端。第一个是复制mymap
到一个新std::map<const int*, double>
的 in myfind
,这是非常低效的。第二个是通过使用const_cast<int*>(mykey)
尽可能避免使用的常量来消除常量。
您可能有一个 const 正确性问题。const int *
可能不是你想的那样。它是一个指向常量整数的指针。这与映射的键类型不同,它是指向(非常量)整数的指针。两者都与int * const
which 是指向(非常量)整数的常量指针不同。问题不在于键值本身是可变的还是不可变的,而在于您存储的指针是可变的还是不可变的。
例如,这编译:
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;
}
你看得到差别吗?在您的原始代码中,编译器标记错误是非常正确的。如果您的函数采用 a const int *
,那么您实际上是承诺不修改int
我传入的指针所指向的指针。但是如果您int *
在 a 的键中使用这样的指针std::map
,您可能会允许某人修改它int
。
在这种特殊情况下,我们知道std::map::find()
不会分配给指针参数,但编译器不会,这就是const_cast<>
其他答案中指出的存在的原因。