指针作为映射 C++ STL 中的键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25122932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pointers as keys in map C++ STL
提问by Ammar Husain
I have a question on how pointers to a custom object are handled when used as Keys in an map. More specifically if I define
我有一个问题,当在地图中用作键时,如何处理指向自定义对象的指针。更具体地说,如果我定义
std::map< CustomClass*, int > foo;
Would the default C++ implementation work to handle these pointers? Or do I need to define a custom comparator function to handle it? In general, is it good practice to use pointers to objects as keys?
默认的 C++ 实现可以处理这些指针吗?还是我需要定义一个自定义比较器函数来处理它?一般来说,使用指向对象的指针作为键是一种好习惯吗?
回答by Neil Kirk
The default implementation will compare the addresses stored by the pointers, so different objects will be considered as different keys. However, the logical state of the object will not be considered. For example, if you use std::string *
as the key, two different std::string
objects with the same text of "Hello"
would be considered a different key! (When stored in the map by their addresses)
默认实现将比较指针存储的地址,因此不同的对象将被视为不同的键。但是,不会考虑对象的逻辑状态。例如,如果您将其std::string *
用作键,则std::string
具有相同文本的两个不同对象"Hello"
将被视为不同的键!(当按他们的地址存储在地图中时)
It's ok to use pointers as keys so long as you understand the important difference above.
只要您理解上面的重要区别,就可以使用指针作为键。
回答by firda
Pointers will be handled but compared as pointers (memory order). You have to pass custom less
functor if you wish to compare the objects:
指针将被处理但作为指针进行比较(内存顺序)。less
如果要比较对象,则必须传递自定义函子:
template<class T> struct ptr_less {
bool operator()(T* lhs, T* rhs) {
return *lhs < *rhs; }};
map<Object*,int,ptr_less<Object>> mymap;
回答by Wojtek Surowka
C++ standard provided specialisation of std::less
for pointers, so yes you can safely use them as map keys etc.
C++ 标准提供了std::less
for 指针的特化,所以是的,您可以安全地将它们用作映射键等。
回答by Steve Townsend
Leaving aside from the legality of this and any possible semantic misunderstandings, addressed already, I cannot think of any reason to use std::map
here rather than std::unordered_map
. There are early intercepts of this in Boost and Visual C++ if you are on a pre-C++11 compiler.
撇开这个的合法性和任何可能的语义误解,已经解决了,我想不出有什么理由在std::map
这里使用而不是std::unordered_map
. 如果您使用的是 C++11 之前的编译器,那么在 Boost 和 Visual C++ 中会有早期拦截。
Since you appear to be using a pointer to represent a unique object, something like boost::flyweightcould be applicable.
由于您似乎使用指针来表示唯一对象,因此可能适用boost::flyweight 之类的内容。
回答by blueskin
Pointers can be used as keys but especially with a std::map (or std::set) I would not advise it. The behavior of the program is not deterministic i.e. when one iterates over the map the order in which the items in the map are iterated is not guaranteed to be the same. It really depends on the memory address of the object (key). Take a look at this example, as you can see irrespective of the insertion order into the map the items are iterated in a deterministic way when the key is a string rather than a pointer.
指针可以用作键,但特别是对于 std::map(或 std::set),我不建议这样做。程序的行为不是确定性的,即当一个人在地图上迭代时,地图中项目的迭代顺序不能保证是相同的。它实际上取决于对象(键)的内存地址。看看这个例子,你可以看到,当键是一个字符串而不是一个指针时,无论映射中的插入顺序如何,项目都会以一种确定性的方式进行迭代。
#include <iostream>
#include <map>
using namespace std;
class SomeClass {
public:
SomeClass(const std::string& name): m_name(name) {}
std::string GetName()const {return m_name; }
bool operator <(const SomeClass& rhs) const { return m_name < rhs.m_name; }
private:
std::string m_name;
};
auto print_seq = [](const auto& seq) { for (const auto& itr: seq) {std::cout << itr.second << " , ";} std::cout << std::endl;};
int main() {
// your code goes here
std::map<SomeClass*, std::string> pointer_keyed_map;
SomeClass s3("object3");
SomeClass s1("object1");
SomeClass s2("object2");
pointer_keyed_map.insert(std::make_pair(&s1, s1.GetName()));
pointer_keyed_map.insert(std::make_pair(&s2, s2.GetName()));
pointer_keyed_map.insert(std::make_pair(&s3, s3.GetName()));
std::cout << "Pointer based keys: object order" << std::endl;
print_seq(pointer_keyed_map);
std::map<SomeClass, std::string> int_keyed_map;
int_keyed_map.insert(std::make_pair(s3, s3.GetName()));
int_keyed_map.insert(std::make_pair(s1, s1.GetName()));
int_keyed_map.insert(std::make_pair(s2, s2.GetName()));
std::cout << "String based keys: object order" << std::endl;
print_seq(int_keyed_map);
return 0;
}