首页 > 科技 > 浅谈C++ initialize_list原理

浅谈C++ initialize_list原理

浅谈initialize_list原理

自从C++11 开始,初始化就引入了一个新的特性,如下:

​可以直接通过一个初始化列表来初始化容器,那么这个是怎么实现的呢?这就和我们今天要说的initializer_list有关了。

1. 引入

先看一个情况,在C语言中,如果我们想要实现一个可变形参的函数,那么应该这么做:

​这里函数必须声明称C调用约定,至于原因,跟栈平衡恢复有关,这里不细讲。

当然在C++中,也可以使用这种情况,不过C++可以使用另外一种技术实现,就是initializer_list,下面我们看一下这种技术的基本使用和原理。

2. initializer_list

2.1 简介

先来看一下C++网站对于这种结构的描述:

This type is used to access the values in a C++ initialization list, which is a list of elements of type const T.

Objects of this type are automatically constructed by the compiler from initialization list declarations, which is a list of comma-separated elements enclosed in braces:

​从这里我们可以知道,这种类型是编译器自动构造的。

2.2 基本使用

这个类提供了如下的操作接口

​关于构造函数,我们有如下构造方法:

1.initializer_list li : 构造一个空的列表。

2.initializer_list li{a, b, c, ...} : 构造一个指定的列表。

2.3 示例

那么 initializer_list具体怎么使用呢?下面给出一个基本的使用例子:

​2.4 原理

先看一下initializer_list的实现过程:

​从这里我们可以发现如下问题:

1.保存const的变量的指针(起始和结束)。

2.构造函数initializer_list() noexcept.

3.构造函数initializer_list(const _Elem *_First_arg, const _Elem *_Last_arg) noexcept

4.initializer_list保存的元素应该是一样的。

从上分析,initializer_list没有类似initializer_list(int, int, int, ...)的构造函数,那么对于initializer_list li = {100, 200, 300, 400, 500}是怎么初始化的呢?

最好的办法就是看看反汇编代码,在VS编译器中(每个编译器的实现可能会不同):

​原理为:

1.在栈上面分配一个数组。

2.取到数组的第一个和最后一个地址的下一个(ebp-18h, ebp-2Ch).

3.然后调用构造函数initializer_list(const _Elem *_First_arg, const _Elem *_Last_arg) noexcept。

也就是说,编译器底层帮忙做了所有的事情。

唉,有人说C++真的很难,我觉得编译器做了太多的事情,也是导致C++难学的原因;因为编译器做得事情越多,使用起来就会越方便,但是理解起来就更加困难。

3. 应用

3.1 容器的使用

在vector中存在如下的构造函数

​那么,我们就可以使用:

​编译器帮我们做得事情:

​3.2 项目使用

我们可以在自己的类或者函数中实现这一个特性,例如:

​反汇编结果如下:

​4. 总结

C++编译器总是瞒着我们做了太多的事情,所有导致我们知其然而不知其所以然;导致我们C++使用越来越简单,理解起来就会越来越复杂;导致我们编写C++越来越简单,但是写出高效的C++代码就会越来越困难。

本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.souzhinan.com/kj/251540.html