std::map如何使用std::string数据为键?类作为键的相关疑问
嘿,我来逐个拆解你的这几个关于std::map的问题,都是C++里使用自定义类型作为键的常见疑惑:
1. 若创建以类为键的std::map,键是否为指向类的指针?
完全不是必须的!std::map的键可以是类的实例对象,不一定非得是指针。不过要注意,默认情况下std::map需要键类型支持<运算符(即operator<),它会用这个运算符来维护内部的有序结构,以及判断键是否“相等”(规则是:如果!(a < b)且!(b < a),就认为a和b是等价的键)。
举个简单例子,比如我们有一个自定义的MyClass,只要给它重载operator<,就能直接作为std::map的键:
#include <map> #include <string> class MyClass { public: std::string name; int id; // 重载<运算符,按id比较 bool operator<(const MyClass& other) const { return id < other.id; } }; // 使用方式 std::map<MyClass, int> myMap; myMap[{ "Alice", 1 }] = 100;
当然你也可以用类的指针作为键,但这时候std::map会默认比较指针的地址,而不是指针指向的对象内容——这通常不是你想要的,除非你确实想区分不同的对象实例(哪怕内容一样)。
2. 既然std::string是类,它如何在std::map中以字符数组数据作为键?
这要归功于std::string已经帮我们做好了两件事:
- 重载了
operator<:std::string的operator<是按**字符串的内容(字典序)**来比较的,而不是比较std::string对象本身的内存地址。 std::map的逻辑是依赖键的<运算符来工作的——当你把std::string作为键时,std::map会调用它的operator<来比较两个字符串的内容,自然就“知晓”要使用字符数组的数据来判断键的顺序和等价性了。
比如:
std::map<std::string, int> strMap; strMap["hello"] = 1; std::string anotherHello = "hello"; strMap[anotherHello] = 2; // 这里会覆盖之前的1,因为"hello"和anotherHello的内容相等,被视为同一个键
这里两个不同的std::string实例(字面量构造的和anotherHello),因为内容相同,通过operator<判断是等价的,所以std::map会把它们当成同一个键处理。
3. 比较器是否可使两个内容匹配的不同类实例被视为相等?
当然可以!这正是自定义比较器的核心用途之一。
默认情况下,如果你的类没有重载operator<,或者默认的operator<不符合你的需求(比如你不想按id比较,而是想按内容比较),你可以给std::map传入一个自定义的比较器,让它按照你定义的规则来判断键的顺序和等价性。
举个例子,假设我们有一个Person类,我们想让姓名和年龄都相同的不同实例被视为同一个键:
#include <map> #include <string> struct Person { std::string name; int age; }; // 自定义比较器:先比姓名,再比年龄 struct PersonComparator { bool operator()(const Person& a, const Person& b) const { if (a.name != b.name) { return a.name < b.name; } return a.age < b.age; } }; // 使用自定义比较器的map std::map<Person, std::string, PersonComparator> personMap; // 两个不同的Person实例,但内容相同 Person p1 = { "Bob", 30 }; Person p2 = { "Bob", 30 }; personMap[p1] = "Engineer"; personMap[p2] = "Designer"; // 这里会覆盖p1的值,因为比较器认为p1和p2是等价的键
在这个例子里,PersonComparator定义了比较规则,std::map会用这个规则来判断:如果!(comp(a,b))且!(comp(b,a)),就认为a和b是等价的键——也就是内容匹配的不同实例会被视为相等。
内容的提问来源于stack exchange,提问作者dfdhfghf56456

