c++之map使用踩坑

描述:

       使用一个map<int,int> m; 可以使用对应的函数插入数据,因为map重载了[]运算符,所以可以通过m[key] = value进行赋值。一般情况,value为默认类型啊,直接使用[]运算符直接操作即可。没什么问题。

 当value为自定义类,会出现相关问题,例如:

#include <iostream>
#include <map>
#include <string>
#include <stdio.h>
using namespace std;

class A {

public:
  A(){
    cout<<"A()"<<",Line:"<<__LINE__<<endl;
  }
  A(int key,int val): key(key),val(val) {
    cout<<"A(int key,int val) = "<<"k="<<key<<"v="<<val<<",Line:"<<__LINE__<<endl;
  }
  A(const A & a) {
    cout<<"A(A & a) =,Line:"<<__LINE__<<endl;
    key = a.key;
    val = a.val;
  }
  const A & operator=(const A & a) { //返回引用可以改变左值。
    cout<<"A & operator=,Line:"<<__LINE__<<endl;
    key = a.key;
    val = a.val;
    return *this;
  }
  int key;
  int val;
};

int main() {
  std::map<int,A> vm = {{1,A(1,1)}}; 

  cout<<"Start vm"<<endl;
  // 使用[]时,先调用默认构造,再调用赋值函数,如果没有实现默认构造,编译会报错,错误如下<<...>>

  /*
   /usr/include/c++/8/tuple:1668:70: 错误:no matching function for call to ‘A::A()’
         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
  */
  所示,或者使用insert_or_assign函数.
  vm[2] = A(2,2);   
  cout<<"End vm"<<endl;  

  return 0;
}
  /*
    A(int key,int val) = k=1v=1,Line:14
    A(A & a) =,Line:17
    A(A & a) =,Line:17
    Start vm
    A(int key,int val) = k=2v=2,Line:14
    A(),Line:11
    A & operator=,Line:22
    End vm
  */

    map中value是自定义类型的,直接使用[]进行存储结时,例中value的调用自身方法为先调用{默认无参构函数,再调用赋值函数}
    所以,如下使用[]存value,必须在student中实现默认构造,不然编译会出错,如下:
    << 
      没有默认无参构造函数,直接编译报错失败:(添加默认构造函即可解决该问题)
      /usr/include/c++/4.8.2/tuple:1090:70: error: no matching function for call to ‘A::A()’
      second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
    >>
    c++17中,解决了该问题,可以直接使用insert_or_assign()
    vm.insert_or_assign(0,A(0,0));

2.使用结构体或者类作为map的key是,需要重载运算符<,不然会就报错,(因为要排序存储,需要自定义对应的排序函数进行判别)

/usr/include/c++/5/bits/stl_function.h:387:20: error: no match for ‘operator<’ (operand types are ‘const Person’ and ‘const Person’)
       { return __x < __y; }

通常使用string直接坐为key,那是因为string重载了运算符<. 

正确使用代码:

#include <iostream>
#include <map>
#include <string>
#include <stdio.h>
using namespace std;

class A {

public:
  A(){
    cout<<"A()"<<",Line:"<<__LINE__<<endl;
  }
  A(int key,int val): key(key),val(val) {
    cout<<"A(int key,int val) = "<<"k="<<key<<"v="<<val<<",Line:"<<__LINE__<<endl;
  }
  A(const A & a) {
    cout<<"A(A & a) =,Line:"<<__LINE__<<endl;
    key = a.key;
    val = a.val;
  }

  
  const A & operator=(const A & a) {
    cout<<"A & operator=,Line:"<<__LINE__<<endl;
    key = a.key;
    val = a.val;
    return *this;
  }

  bool operator< (const A & a) const {  // 重载运算符,因为插入map是需要进行当前key值的比较排
    return key < a.key || val < a.val;
  }
  int key;
  int val;
};


void display(std::map<A,int> mm){
  for(const auto & iter:mm) {
    cout<<iter.first.key<<"--"<<iter.first.val<<"--"<<iter.second<<endl;
  }
}
int main() {

  std::map<A,int> sm;
  sm[A(4,5)] = 1;
  display(sm);

  return 0;
}
输出:

4--5--1
4--6--2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值