【问题标题】:Using pair as key in a map (C++ / STL)在映射中使用对作为键 (C++ / STL)
【发布时间】:2011-03-17 16:06:25
【问题描述】:

我想使用 STL 中的一对作为映射的键。

#include <iostream>
#include <map>

using namespace std;

int main() {

typedef pair<char*, int> Key;
typedef map< Key , char*> Mapa;

Key p1 ("Apple", 45);
Key p2 ("Berry", 20);

Mapa mapa;

mapa.insert(p1, "Manzana");
mapa.insert(p2, "Arandano");

return 0;

}

但是编译器会抛出一堆不可读的信息,而且我对 C 和 C++ 很陌生。

如何在地图中使用一对作为键?一般来说,我如何使用任何类型的结构(对象、结构等)作为映射中的键?

谢谢!

【问题讨论】:

  • 以后,请发布您收到的错误消息。否则,人们通常很难或不可能帮助您。 :)
  • 如果您确实发布了这些错误,我相信我们也可以帮助解释它们的含义以及您将来看到它们时如何解释它们。
  • 请注意,使用字符串文字,比较的是字符串的地址,而不是字符串本身。你最好使用std::string

标签: c++ stl map std-pair


【解决方案1】:

std::map::insert 接受一个参数:键值对,因此您需要使用:

mapa.insert(std::make_pair(p1, "Manzana"));

您应该在类型中使用 std::string 而不是 C 字符串。就像现在一样,您可能不会得到您期望的结果,因为在映射中查找值将通过比较指针而不是通过比较字符串来完成。

如果您真的想使用 C 字符串(同样,您不应该这样做),那么您需要在您的类型中使用 const char* 而不是 char*

一般而言,我如何使用任何类型的结构(对象、结构等)作为映射中的键?

您需要为键类型重载 operator&lt; 或使用自定义比较器。

【讨论】:

  • mapa[p1] = "Manzana"; 更短
  • @Peter: operator[] 具有不同的语义,我建议不要使用它将对象插入map (如果一个新对象不存在,它会插入一个新对象,然后覆盖立即新创建的临时对象)。
  • 哇,这是一个丑陋的错误,我忘了做这对了。对不起!现在可以了,但是当我使用 char* 而不是 const char* 时它不起作用。在这种情况下, const char* 与 char* 有什么关系?谢谢!
  • @ccarpenterg:不用向我道歉。 :-) 字符串字面量的类型为const char[],pair 类型的成员类型为char*; pair 构造函数不能删除 const 限定符。那就是说;真的:使用std::string,使用指针作为映射键几乎总是一个坏主意。
  • @JamesMcNellis 你能把它更新到现代 C++ 吗?我一直想知道我的std::map 使用std::pair 没有问题,直到我注意到since C++14 it has operator&lt; defined
【解决方案2】:

这是对相关代码的有效重写:

#include <map>
#include <string>

class Key
{
  public: 
    Key(std::string s, int i)
    {
      this->s = s;
      this->i = i;
    }
    std::string s;
    int i;
    bool operator<(const Key& k) const
    {
      int s_cmp = this->s.compare(k.s);
      if(s_cmp == 0)
      {
        return this->i < k.i;
      }
      return s_cmp < 0;
    }
};

int main()
{


  Key p1 ("Apple", 45);
  Key p2 ("Berry", 20);

  std::map<Key,std::string> mapa;

  mapa[p1] = "Manzana";
  mapa[p2] = "Arandano";

  printf("mapa[%s,%d] --> %s\n",
    p1.s.c_str(),p1.i,mapa.begin()->second.c_str());
  printf("mapa[%s,%d] --> %s\n",
    p2.s.c_str(),p2.i,(++mapa.begin())->second.c_str());

  return 0;
}

【讨论】:

【解决方案3】:

替代詹姆斯麦克内利斯所说的:

mapa.insert(std::make_pair(p1, "Manzana"));

你可以使用mapa.insert({p1, "Manzana"});

【讨论】:

  • @ccarpenterg:这应该是 C++14 的首选和接受的答案!
【解决方案4】:

这与您想要做的类似版本,只需更改数据类型,仅此而已。另外,请使用 c++ 字符串,而不是我们在 c 中使用的字符串。

#include<bits/stdc++.h>
using namespace std;
#define  ll long long int
typedef pair<ll,ll> my_key_type;
typedef map<my_key_type,ll> my_map_type;
int  main()
{
    my_map_type m;
    m.insert(make_pair(my_key_type(30,40),6));
}   

【讨论】:

    【解决方案5】:

    std::map::emplace 是你的朋友。

    mapa.emplace(p1, "Manzana");
    

    【讨论】:

      【解决方案6】:

      这将完全符合您的要求

      #include<bits/stdc++.h>
      using namespace std;
      int main()
      {
          map<pair<string, long long int>, string> MAP;
          pair<string, long long int> P;
          MAP.insert(pair<pair<string, long long int>, string>(pair<string, long long int>("Apple", 45), "Manzana"));
          MAP.insert(pair<pair<string, long long int>, string>(pair<string, long long int>("Berry", 20), "Arandano"));
          P = make_pair("Berry", 20);
          //to find berry, 20
          cout<<MAP[P]<<"\n";
          return 0;
      }
      

      【讨论】:

      • 我想听听你的建议。
      • 见朱利安的回答。您的代码不可维护。 “更容易重写然后修复”的完美示例。
      猜你喜欢
      • 2014-09-27
      • 1970-01-01
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 2019-08-30
      • 1970-01-01
      相关资源
      最近更新 更多