为什么初始化映射时不能省略大括号

Why can not omit braces when initializing map?

本文关键字:不能省 初始化 映射 为什么      更新时间:2023-10-16

受到这个答案的启发,我尝试了下一个例子:

#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"},
    };

但是为什么在上例中编译失败呢?

因为映射是非聚合的,并且包含非聚合元素(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

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

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

8.5.1骨料[dcl.init.agr]

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

(第11段)

在形式的声明中

T x = { a };

可以在初始值设定项列表中删除大括号,如下所示。如果初始值设定项列表以左大括号开头,然后是后面的逗号分隔的初始值设定项子句列表初始化亚集合体;有更多是错误的初始值设定项子句多于成员。但是,如果初始值设定项列表对于不以左大括号开头的子聚合,则仅列表中有足够的初始值设定项子句用于初始化子集体的成员;任何剩余的初始值设定项子句都是左键以初始化聚合的下一个成员当前子聚合是成员。

我已经很久没有做C++了,但我的猜测是因为std::map需要一组单独的对象,每个对象都包含一个键和一个值对。

只有一个单独的项目列表是没有意义的,而且也很难阅读(以确保你有很多项目可以被二整除)。