1

这是我的问题的大致代码。首先,我们有一个带有构造函数的结构体:

struct Pair{
Pair(int a, int b): (first (a) , second (b) ) {}
int first;
int second;
};

在地图中使用

map<string, Pair> mymap;

我想在一个函数中初始化这个地图

void f(map<string, Pair>* mymap, string c,int x, int y )
{
(*mymap)[c]=Pair(x,y);
}

但是编译器首先说它找不到合适的构造函数,然后下一行是没有为构造函数提供足够的参数。

我的一个朋友告诉我,我应该这样写函数:

void f(map<string, Pair>& mymap, const string& c,int x, int y )
{
  if (mymap.find(c) != mymap.end()) {
    mymap[c] = Pair(x,y);
   }
}

但他无法解释为什么这里应该使用Type&而不是Type *,我想澄清这一点。谁能解释一下?

4

4 回答 4

3

问题是operator[]在地图中要求值类型是默认可构造的。如果您不希望您Pair的默认可构造,则必须避免使用operator[]

void f(map<string, Pair>& mymap, string c,int x, int y )
{
   mymap.insert( std::make_pair(c,Pair(x,y)) );
}

您可能误解了您朋友的建议。问题operator[]不在于它需要默认构造函数,如果它需要创建一个新元素,而是它需要它以防万一它可能需要。也就是说,元素是否事先存在并不重要。


如果您还打算更新,那么您还需要考虑该选项:

void f(map<string, Pair>& mymap, string c,int x, int y )
{
   auto res = mymap.insert( std::make_pair(c,Pair(x,y)) );
   if ( !res.second )
      res.first->second = Pair(x,y);
}

基本上,该insert操作返回一对指向键的迭代器和一个布尔值,指示它是否insert创建了对象或者它是否已经存在(在这种情况下,映射中的值未修改)。通过存储结果,我们可以测试,如果insert没有创建值,我们可以通过返回的迭代器更新它。

于 2012-07-27T16:03:04.043 回答
2

在地图上调用operator[]将要求您的类型是默认可构造的。您可以通过使用map::insertmap::emplace来避免这种情况

于 2012-07-27T16:01:47.277 回答
2

您将需要一个默认的contrructor:

Pair(): first () , second () {}

这是 map 所需要的,它 在使用不存在的键调用时operator[]创建一个默认构造的 -mapped_type

和一个实现严格弱排序的小于运算符:

struct Pair {
  // as before
  bool operator<(const Pair& rhs) const {
     / some code to implement less-than
  }
};

或者您可以将比较函子或函数实现严格弱排序作为第三个模板参数传递。

于 2012-07-27T16:03:42.793 回答
0

标准容器需要一个默认构造函数。他们将operator=在构建后的某个时候使用 来设置正确的值。

于 2012-07-27T15:58:28.653 回答