在哪里可以使用列表初始化? [英] Where can we use list initialization?

查看:143
本文介绍了在哪里可以使用列表初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题已经涵盖了什么POD和聚合,并提供了一些聚合初始化的例子。

This question already covers what PODs and aggregates are, and provides some examples on aggregate initialization.

这里的问题是在哪里可以使用列表初始化

strong>您可以在哪里使用(缺少更好的字词)列表分配

Also where can you use (in lack of a better term) list assignment?

答案应该同时处理C ++ 03和C ++ 11,突出它们之间的差异。

An answer should deal with both C++03 and C++11, highlighting the differences between them.

推荐答案

C ++ 03



列表初始化



在C ++ 03中,你只能使用列表初始化的聚合(C ++ 03 [dcl.init。 aggr])和标量(C ++ 03 [dcl.init] / 13)类型:

C++03

List initialization

In C++03 you can only use list-initialization for aggregates (C++03 [dcl.init.aggr]) and scalar (C++03 [dcl.init]/13) types:

int i = { 0 };
POD pod = { 0, 1, 2 };



列表分配



列表赋值在C ++ 03的任何地方。 [expr.ass] / 1中显示的语法不允许作业右侧的大括号列表。

List assignment

You could not use "list-assignment" anywhere in C++03. The grammar shown in [expr.ass]/1 does not allow a braced list on the right of an assignment.

在C ++ 11中,你几乎可以在任何地方使用list-initialization创建一个变量(参见[dcl.init ] in C ++ 11和[dcl.init.list] / 1,其中列出了允许列表初始化的上下文)例如

In C++11 you can use list-initialization pretty much anywhere you can create a variable (see [dcl.init] in C++11 and [dcl.init.list]/1 which lists contexts where list-initialization is allowed) e.g.

struct Base { };

struct Class : Base
{
    int mem{ 0 };  // init non-static data member

    Class(int i)
    : Base{}   // init base class
    , mem{i}   // init member
    {
      int j{i};   // init local var

      int k = int{0};  // init temporary

      f( { 1 } );  // init function arg

      int* p = new int{1};  // new init

      // int k(int());  // most vexing parse, declares function
      int k{ int{} };   // ok, declares variable

      int i[4]{ 1,2,3,4 };   // init array
    }

    Class f(int i)
    {
      return { i };   // init return value
    }
};

Class c{1};   // init global var

上面的大多数初始化声明一个 int 或数组 int ,但是相同的语法可以用于调用类类型的构造函数(如构成 Class variable)

Most of the initializations above declare an int or array of int but the same syntax can be used to call a constructor for a class type (like the two lines that construct a Class variable)

除了在几乎任何可以初始化变量的上下文中都有效外,列表初始化也可以与另一个C ++ 11的新特性: std :: initializer_list 类模板。一个带有 std :: initializer_list 参数的构造函数可以传递一个任意长的值列表,构造函数可以通过 begin() std :: initializer_list 的成员函数 end()。这个新功能的主要优点是,它允许您初始化一个容器与一组元素,例如。 vector< int> v {0,1,2,3,4,5} ,而不是构造容器,然后插入值。

As well as being valid in almost any context where you can initialize a variable, list-initialization also interacts well with another new feature of C++11: the std::initializer_list class template. A constructor that takes a std::initializer_list argument can be passed an arbitrarily-long list of values, which the constructor can iterate over via begin() and end() member functions of the std::initializer_list. The main benefit of this new feature is that it allows you to initialize a container with a set of elements, e.g. vector<int> v{ 0, 1, 2, 3, 4, 5 } rather than constructing the container and then inserting values.

列表初始化也可以用于braced-init-list中的元素,允许嵌套列表初始化映射m {{a,b},{c,d}} 而不是映射m {Map :: value_type(a,b) :: value_type(c,d)}

List-initialization can also be used for elements within a braced-init-list, allowing nested list-initialization e.g. Map m{ {a, b}, {c, d} } rather than Map m{ Map::value_type(a, b), Map::value_type(c, d) }

唯一的时间列表初始化不正确的事情是当试图构造一个类类型通过调用构造函数,如果类有另一个构造函数取一个 std :: initializer_list ,作为列表初始化将总是喜欢的构造函数取一个 std :: initializer_list 例如

The only time list-initialization doesn't do the right thing is when trying to construct a class type by calling a constructor if the class has another constructor taking a std::initializer_list, as list-initialization will always prefer the constructor taking a std::initializer_list e.g.

// attempts to create vector of 5 elements, [1,1,1,1,1]
// but actually creates a vector with two elements, [5,1] 
std::vector<int> v{ 5, 1 };

这不会调用向量(size_type,const int& / code>构造函数,而不是调用向量(initializer_list< int>)构造函数。

在C ++ 11中,您可以使用list-assignment

In C++11 you can use "list-assignment"


  • 分配给标量类型时,如果 braced-init-list 有一个可以转换(不缩小)变量类型的元素(见[expr.ass] / 9)

  • 当赋值的左操作数是具有用户定义的赋值运算符的类类型时,在这种情况下,
    braced-init-list 用于初始化操作员(见[expr.ass] / 9)。这包括 operator =(std :: initializer_list< T>)这两种情况,其中右操作数中的 braced-init-list 可转换为 T ,例如为 std :: vector< int> v 将用[1,2,3]替换容器的内容,而当 > braced-init-list 可以通过合适的构造函数隐式转换为运算符的参数类型,例如

  • when assigning to a scalar type, if the braced-init-list has a single element that is convertible (without narrowing) to the variable's type (see [expr.ass]/9)
  • when the left operand of the assignment is a class type with a user-defined assignment operator, in which case the braced-init-list is used to initialize the argument of the operator (see [expr.ass]/9). This includes both cases like operator=(std::initializer_list<T>) where the elements of the braced-init-list in the right operand are convertible to T, e.g. for the std::vector<int> v above, v = { 1, 2, 3 } will replace the container's contents with [1,2,3] and when the braced-init-list can be implicitly-converted to the operator's argument type, via a suitable constructor e.g.

code> struct A {
int i;
int j;
};

struct A { int i; int j; };

struct B {
  B& operator=(const A&);
};

int main() {
  B b;
  b = { 0, 1 };
}

main 的最后一行

上的
将被隐式转换为临时 A ,那么 B 的赋值运算符将以该临时变量作为其参数来调用。

On the last line of main the braced-init-list will be implicitly-converted to a temporary A then the assignment operator of B will be called with that temporary as its argument.

这篇关于在哪里可以使用列表初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆