When do we use Initializer List in C++?
Initializer List is used to initialize data members of a class. The list of members to be initialized is indicated with constructor as a comma separated list followed by a colon.
Following is an example that uses initializer list to initialize x and y of Point class.
1 #include<iostream>
2 using namespace std;
3
4 class Point {
5 private:
6 int x;
7 int y;
8 public:
9 Point(int i = 0, int j = 0):x(i), y(j)
10 {
11 }
12 /* The above use of Initializer list is optional as the
13 constructor can also be written as:
14 Point(int i = 0, int j = 0)
15 {
16 x = i;
17 y = j;
18 }
19 */
20
21 int getX() const
22 {
23 return x;
24 }
25 int getY() const
26 {
27 return y;
28 }
29 };
30
31 int main()
32 {
33 Point t1(10, 15);
34
35 cout<<"x = "<<t1.getX()<<", ";
36 cout<<"y = "<<t1.getY();
37
38 return 0;
39 }
40
41 /* OUTPUT:
42 x = 10, y = 15
43 */
The above code is just an example for syntax of Initializer list. In the above code, x and y can also be easily initialed inside the constructor.
But there are situations where initialization of data members inside constructor doesn’t work and Initializer List must be used.
Following are such cases:
1) For initialization of non-static const data members: const data members must be initialized using Initializer List.
In the following example, “t” is a const data member of Test class and is initialized using Initializer List.
1 #include<iostream>
2 using namespace std;
3
4 class Test
5 {
6 const int t;
7 public:
8 Test(int t):t(t) //Initializer list must be used
9 {
10 }
11 int getT()
12 {
13 return t;
14 }
15 };
16
17 int main()
18 {
19 Test t1(10);
20 cout<<t1.getT();
21 return 0;
22 }
23
24 /* OUTPUT:
25 10
26 */
2) For initialization of reference members:Reference members must be initialized using Initializer List.
In the following example, “t” is a reference member of Test class and is initialized using Initializer List.
1 // Initialization of reference data members
2 #include<iostream>
3 using namespace std;
4
5 class Test
6 {
7 int &t;
8 public:
9 Test(int &t):t(t)
10 {
11 } //Initializer list must be used
12 int getT()
13 {
14 return t;
15 }
16 };
17
18 int main()
19 {
20 int x = 20;
21 Test t1(x);
22 cout<<t1.getT()<<endl;
23 x = 30;
24 cout<<t1.getT()<<endl;
25 return 0;
26 }
27 /* OUTPUT:
28 20
29 30
30 */
3) For initialization of member objects which do not have default constructor.
In the following example, an object “a” of class “A” is data member of class “B”, and “A” doesn’t have default constructor. Initializer List must be used to initialize "a".
1 #include <iostream>
2 using namespace std;
3
4 class A
5
6 {
7 int i;
8 public:
9 A(int );
10 };
11
12 A::A(int arg)
13
14 {
15 i = arg;
16 cout << "A's Constructor called: Value of i: " << i << endl;
17 }
18
19 // Class B contains object of A
20 class B
21
22 {
23 A a;
24 public:
25 B(int );
26 };
27
28 B::B(int x):a(x)
29
30 {
31
32 //Initializer list must be used
33 cout << "B's Constructor called";
34 }
35
36 int main()
37
38 {
39 B obj(10);
40 return 0;
41 }
42 /* OUTPUT:
43 A's Constructor called: Value of i: 10
44 B's Constructor called
45 */
If class A had both default and parameterized constructors, then Initializer List is not must if we want to initialize “a” using default constructor, but it is must to initialize “a” using parameterized constructor.
4) For initialization of base class members : Like point 3, parameterized constructor of base class can only be called using Initializer List.
1 #include <iostream>
2 using namespace std;
3
4 class A
5 {
6 int i;
7 public:
8 A(int );
9 };
10
11 A::A(int arg)
12 {
13 i = arg;
14 cout << "A's Constructor called: Value of i: " << i << endl;
15 }
16
17 // Class B is derived from A
18 class B: A
19 {
20 public:
21 B(int );
22 };
23
24 B::B(int x):A(x)
25 {
26 //Initializer list must be used
27 cout << "B's Constructor called";
28 }
29
30 int main()
31 {
32 B obj(10);
33 return 0;
34 }
5) When constructor’s parameter name is same as data member
If constructor’s parameter name is same as data member name then the data member must be initialized either using this pointer or Initializer List. In the following example, both member name and parameter name for A() is “i”.
1 #include <iostream>
2 using namespace std;
3
4 class A
5 {
6 int i;
7 public:
8 A(int );
9 int getI() const
10 {
11 return i;
12 }
13 };
14
15 A::A(int i):i(i)
16 {
17 } // Either Initializer list or this pointer must be used
18
19 /* The above constructor can also be written as
20 A::A(int i)
21 {
22 this->i = i;
23 }
24 */
25
26 int main()
27 {
28 A a(10);
29 cout<<a.getI();
30 return 0;
31 }
32 /* OUTPUT:
33 10
34 */
6) For Performance reasons:
It is better to initialize all class variables in Initializer List instead of assigning values inside body.
Consider the following example:
1 // Without Initializer List
2 class MyClass
3 {
4 Type variable;
5 public:
6 MyClass(Type a)
7 {
8 // Assume that Type is an already
9 // declared class and it has appropriate
10 // constructors and operators
11 variable = a;
12 }
13 };
Here compiler follows following steps to create an object of type MyClass
1. Type’s constructor is called first for “a”.
2. The assignment operator of “Type” is called inside body of MyClass() constructor to assign
variable = a;
3. And then finally destructor of “Type” is called for “a” since it goes out of scope.
1 // With Initializer List
2 class MyClass
3 {
4 Type variable;
5 public:
6 MyClass(Type a):variable(a)
7 {
8 // Assume that Type is an already
9 // declared class and it has appropriate
10 // constructors and operators
11 }
12 };
Now consider the same code with MyClass() constructor with Initializer List With the Initializer List, following steps are followed by compiler:
1. Copy constructor of “Type” class is called to initialize : variable(a). The arguments in initializer list are used to copy construct “variable” directly.
2. Destructor of “Type” is called for “a” since it goes out of scope.
As we can see from this example if we use assignment inside constructor body there are three function calls: constructor + destructor + one addition assignment operator call. And if we use Initializer List there are only two function calls: copy constructor + destructor call. See this post for a running example on this point.
This assignment penalty will be much more in “real” applications where there will be many such variables. Thanks to ptr for adding this point.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
转载请注明:http://www.cnblogs.com/iloveyouforever/
2013-11-26 10:36:51
When do we use Initializer List in C++?的更多相关文章
- 使用Spire组件抛出异常The type initializer for 'spr857' threw an exception
使用Spire组件抛出异常The type initializer for 'spr857' threw an exception 我使用免费的Spire.Xls组件尝试去转换Excel文档到PDF文 ...
- Don’t Use Accessor Methods in Initializer Methods and dealloc 【初始化和dealloc方法中不要调用属性的存取方法,而要直接调用 _实例变量】
1.问题: 在dealloc方法中使用[self.xxx release]和[xxx release]的区别? 用Xcode的Analyze分析我的Project,会列出一堆如下的提示:Inco ...
- C#中异常:“The type initializer to throw an exception(类型初始值设定项引发异常)”的简单分析与解决方法
对于C#中异常:“The type initializer to throw an exception(类型初始值设定项引发异常)”的简单分析,目前本人分析两种情况,如下: 情况一: 借鉴麒麟.NET ...
- System.Security.SecurityException The type initializer for 'System.Data.Entity.Internal.AppConfig' threw an exception
[15/08/19 00:03:10] [DataManager-7292-ERROR] System.Reflection.TargetInvocationException: Exception ...
- iOS: 聊聊 Designated Initializer(指定初始化函数)
iOS: 聊聊 Designated Initializer(指定初始化函数) 一.iOS的对象创建和初始化 iOS 中对象创建是分两步完成: 分配内存 初始化对象的成员变量 我们最熟悉的创建NSOb ...
- ios 修正waring:Method override for the designated initializer of the superclass '-init' not found
swift引入后,为了使oc和swift更相近,对oc的初始化方法也进行了修正,具体说明,见下面的链接,这个waring的最简单的修正方法是,到相应类的头文件中,去掉在自定义初始化方法后面的 NS_D ...
- System.TypeInitializationException: The type initializer for 'Mono.Unix.Native.Stdlib' threw an exception.
08-31 17:02:03: ### DEBUG ##########################System.TypeInitializationException: The type ini ...
- React和ES6(二)ES6的类和ES7的property initializer
React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...
- initializer for conditional binding must have optional type not AVAudioPlayer
if let buttonBeep = self.setupAudioPlayerWithFile("ButtonTap", type: "wav") { ...
- 正确编写Designated Initializer的几个原则
Designated Initializer(指定初始化器)在Objective-C里面是很重要的概念,但是在日常开发中我们往往会忽视它的重要性,以至于我们写出的代码具有潜藏的Bug,且不易发现.保证 ...
随机推荐
- void * 是什么?
最近遇到void *的问题无法解决,发现再也无法逃避了(以前都是采取悄悄绕过原则),于是我决定直面它. 在哪遇到了? 线程创建函数pthread_create()的最后一个参数void *arg,嗯? ...
- linux 安装docker(一)
1.安装环境 此处在Centos7进行安装,可以使用以下命令查看CentOS版本 lsb_release -a 在 CentOS 7安装docker要求系统为64位.系统内核版本为 3.10 以上,可 ...
- Swift-Framework(一)访问资源文件
摘要 Framework 就是在 APP 应用中的一种封装功能的表现形式,虽然不能独立运行,但是也可以在它里面存放和访问图片.语音等资源文件,可算是麻雀虽小,五脏俱全. 毕竟不是 APP 工程,所以 ...
- SDKStyle的Framework项目使用旧版项目文件生成的Nuget包遇到的问题
随笔-2021-11-10 SDKStyle的Framework项目使用旧版项目文件生成的Nuget包遇到的问题 简介 C#从NetCore之后使用了新版的项目文件,SDK-Style项目,新版本的项 ...
- cesium开发(1)搭建 vue + cesium开发环境
进入新公司一段时间了,新公司业务主要从事卫星方面等webgl的开发,主要使用了leafletjs和cesium,其中cesium难度较大,需求较多,再进行了一段时间的使用开发后依旧感到有些力不从心, ...
- python实现图片的ROI(region of interest)和泛洪填充
目录: (一)ROI操作 (1)获取感兴趣区域(2)还原操作 (二)泛洪填充floodFill 正文: (一)ROI操作 感兴趣区(Region of Interest,ROIs) 是图像的一部分,它 ...
- [noi109]排队
题目要求其实相当于要让大于和小于m的数的个数都不超过n/2,因此当要对一个数处理时,要么把它改成m,要么不作修改,根据这个贪心就可以完成了. 1 #include<bits/stdc++.h&g ...
- [luogu5423]Valleys
先考虑不要求有洞,那么可以将所有权值排序,然后不断插入,那么一个连通块就是一个答案,加上连通块大小即可考虑并查集如何判断是否有洞,可以发现对于任意一个无洞的直角多边形,都有$90度内角-90度外角=4 ...
- ES6学习 第二章 变量的解构赋值
前言 该篇笔记是第二篇 变量的解构赋值. 这一章原文链接: 变量的解构赋值 解构赋值 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 解构 ...
- es基本概念
电商实时数据分析平台需要学些什么? [运营指标,流量指标,销售转化指标,客户价值指标,商品指标,营销指标,风险控制指标,市场竞争指标]等电商指标数据. 检索,数据更新,排序,分词,query等缓存机 ...