为什么在初始化地图时不能省略大括号?

时间:2012-07-31 14:36:54

标签: c++ c++11 initializer-list

受到this answer的启发,我尝试了下一个例子:

#include <map>
#include <string>
#include <iostream>

int main()
{
  const std::map< int, std::string > mapping = {
      1, "ONE",
      2, "TWO",
    };

  const auto it = mapping.find( 1 );
  if ( mapping.end() != it )
  {
    std::cout << it->second << std::endl;
  }
  else
  {
    std::cout << "not found!" << std::endl;
  }
}

并且编译失败并出现下一条错误消息(g ++ 4.6.1):

gh.cpp:11:5: error: could not convert '{1, "ONE", 2, "TWO"}' from '<brace-enclosed initializer list>' to 'const std::map<int, std::basic_string<char> >'

我知道如何解决它:

  const std::map< int, std::string > mapping = {
      {1, "ONE"},
      {2, "TWO"},
    };

但为什么编译在顶部示例中失败?

3 个答案:

答案 0 :(得分:24)

因为地图是非聚合的,并且包含非聚合元素(std::pair<key_type, mapped_type>),所以它需要一个初始化列表,其中包含每个对的初始化列表。

std::pair<int,int> p0{ 1,2 }; // single pair
std::map<int, int> m { { 1,2 } }; // map with one element
std::map<int, int> m { { 1,2 }, { 3,4} }; // map with two elements

请记住,大括号的规则适用于聚合,因此它们不适用于此。

答案 1 :(得分:9)

C ++ 11标准只允许在目标是聚合时省略大括号:

  

8.5.1聚合[dcl.init.aggr]

     

聚合是一个没有用户提供的数组或类(第9条)   构造函数(12.1),非静态的支撑或相等初始化器   数据成员(9.2),没有私有或受保护的非静态数据成员   (第11条),没有基类(第10条),也没有虚函数   (10.3)。

     

...

     

(第11段)

     

在表格

的声明中
T x = { a };
     

大括号可以在初始化列表中省略,如下所示。如果   初始化列表以左括号开头,然后是成功   逗号分隔的initializer-clauses列表初始化成员   分组;有更多的是错误的   初始化者 - 条款比成员。但是,如果是初始化列表   对于子聚合不是以左括号开始,而是仅以左括号开头   从列表中获取足够的初始化子句来初始化   分组成员;任何剩余的初始化条款都是   左边初始化聚合的下一个成员   current subaggregate是会员。

答案 2 :(得分:3)

自从我完成C ++以来已经很久了,但我的猜测是因为std::map期待一组单独的对象,每个对象都包含一个键和一个值对。

单个列表中的单个项目没有意义,并且也很难阅读(以确保您有多个项目可以被2整除)。