C++中关于map使用需要注意的一些坑

一、char*与string不一样!

1、例1:
std::map<std::string, int> my_map;
map.insert(pair<std::string, int>("hello", 1));
cout << "my_map_value = " << my_map["hello"] << endl;

结果:1.

对于这个结果,大家并不会感到意外,因为在C++中,std::map的键类型必须是可比较的,也就是说,它们必须能够使用比较运算符(如 <)进行排序。而std::string 对象可以正确地比较其内容,因此使用 std::map<std::string, int> 将允许你使用字符串字面量并确保它们被视为相同的键。

2、例2:
std::map<char*, int>my_map;
char str1[] = {(char*)"hello"};
my_map.insert(pair<char*, int>(str1, 1));
cout << "my_map_value1 = " << my_map["hello"] << endl;
cout << "my_map_value2 = " << my_map[str1] << endl;

结果:my_map_value1 = x(一个未知的数)

           my_map_value2 = 1

这个结果意不意外,最开始我使用map的时候,因为明确不使用string,因此使用了char*作为键的类型。但是对于原始的 char* 类型,这些指针之间的比较实际上是基于它们在内存中的地址值,而不是它们所指向的字符串内容。这意味着即使两个 char* 指向完全相同的字符串内容,只要它们的地址不同,它们就会被视为不同的键。

当你尝试在 std::map<char*, int> 中使用 [] 运算符时,如果传递的是一个字符串字面量,例如 "key",这实际上会被转换为一个临时的 const char* 对象。每次调用 [] 运算符时,都会创建一个新的临时 const char*,这意味着即使你传递了看似相同的字符串字面量,每次也会得到一个不同的指针,因此每次都会创建一个新的键条目,而不是更新已存在的键。

为了避免这种问题,有几种解决方案:
  1. 使用std::string作为键std::string 对象可以正确地比较其内容,因此使用 std::map<std::string, int> 将允许你使用字符串字面量并确保它们被视为相同的键。

  2. 使用自定义比较器: 你可以为 std::map 提供一个自定义的比较函数或比较对象,该函数将比较 char* 所指向的字符串内容,而不是它们的地址。这样,即使 char* 的地址不同,但只要它们指向相同的字符串,它们就会被视为相等的键。

以下是GPT中的一个例子,大家可以参考下

// 定义一个比较结构体,用于比较两个const char*类型的字符串
struct Compare {
    // 重载比较运算符,返回lhs和rhs比较的结果,如果lhs小于rhs则返回true
    bool operator()(const char* lhs, const char* rhs) const {
        // 使用标准库函数strcmp比较两个字符串,如果lhs小于rhs,strcmp返回负数,因此结果为真
        return std::strcmp(lhs, rhs) < 0;
    }
};

int main() {
    // 使用Compare作为比较器,创建一个map,其中键是const char*类型,值是int类型
    std::map<const char*, int, Compare> m;

    // 使用字符串字面量"foo"作为键,插入值1到map中
    m["foo"] = 1;
    // 再次使用字符串字面量"foo"作为键,这次插入值2,由于键相同(根据Compare比较器),值会被更新为2
    m["foo"] = 2;

    // 输出map的大小,应为1,因为"foo"键只对应一个元素
    std::cout << "Size of map: " << m.size() << std::endl; // 输出: 1

    return 0;
}

当map中传入第三个参数Compare后,在例2中, my_map_value1的值可以返回1,因为重写了比较器,通过比较字符串的内容来将char*与字符串常量视为相等的键,从而获得相同的值。

总之,在 std::map 中使用 char* 作为键时要小心,因为它可能会导致意外的结果,除非你采取措施确保键的正确比较。

 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值