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

BЈо*_*вић 13 c++ initializer-list c++11

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

#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;
  }
}
Run Code Online (Sandbox Code Playgroud)

编译失败,出现下一条错误消息(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> >'
Run Code Online (Sandbox Code Playgroud)

我知道如何解决它:

  const std::map< int, std::string > mapping = {
      {1, "ONE"},
      {2, "TWO"},
    };
Run Code Online (Sandbox Code Playgroud)

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

jua*_*nza 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
Run Code Online (Sandbox Code Playgroud)

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

  • @BЈовић实际上,`std :: pair`不是聚合.我不知道`{}`何时可以省略*的规则,但在这种情况下允许它是没有意义的.我可以稍后再说... (3认同)

Mic*_*urr 9

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

8.5.1聚合[dcl.init.aggr]

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

...

(第11段)

在表格的声明中

T x = { a };
Run Code Online (Sandbox Code Playgroud)

大括号可以在初始化列表中省略,如下所示.如果初始化列表以左括号开头,则后续的逗号分隔的initializer-clause列表初始化子集合的成员; 如果有比成员更多的初始化子条款是错误的.但是,如果子聚合的初始化列表不以左括号开头,则只从列表中获取足够的初始化子句来初始化子聚合的成员; 剩下的任何初始化子句用于初始化当前子聚合为成员的聚合的下一个成员.

  • @BЈовић错了,它不是聚合的.它有构造函数和所有. (3认同)