网上有朋友问初始化列表的问题,所谓的初始化列表其实就是类成员初始化列表(Member Initialization List)的简单说法。
1)
基本概念,初始化列表的形式
#include <iostream>
using namespace std;
class MemberInitializationList
{
private:
int i;
int j;
public:
MemberInitializationList(int val) :
j(val), i(j) //
j(val), i(j)就是所谓的成员初始化列表
{
}
inline void printInfo()
{
cout << "i = " << i << ", j = " << j << endl;
}
};
int main(void)
{
MemberInitializationList MIL(10);
MIL.printInfo();
return 0;
}
运行结果:
i = -858993460 j = 10
j如愿以偿被初始化为10,但是i的值为什么是一个奇怪的数字,而不是意想中的10呢?
答案是有些细微的地方需要注意:成员初始化列表的初始化顺序是由类中的成员声明次序决定的,而不是由initialization
list中的排列次序决定的。在本例中,先初始化i然后再初始化j。initialization
list中的i(j),表明将j的值赋给i,而此时j还没有被初始化,其值不确定,所以i的值也就不能确定,这就是运行结果中为什么i的值比较奇怪的原因了。
在任何explicit user code之前,编译器会一一操作initialization
list,以适当次序在构造函数内安插初始化操作。
需要说明的是,据说除了g++编译器会对这种情况给予warning外,其它的编译器都不会给出相关的警告信息。
如果把本例中的构造函数改成:
MemberInitializationList(int val) : i(val), j(i)
{
}
再运行的结果就正确了:
i = 10 j = 10
2)
为什么要使用member initialization list?
根据Stanley Lippman的Inside
C++ Object Model,采用member initialization list的方法的效率比较高,即
MemberInitializationList(int val) : i(val), j(i)
{
}
的效率要比
MemberInitializationList(int val)
{
i = val;
j = I;
}
高。理由是后者会产生临时性的变量,然后要调用赋值运算符赋给真正的变量,再然后摧毁那个临时性的变量。是否真的是这样呢?我们来做一个试验证明之。验证程序如下:
#include <iostream>
#include <time.h>
using namespace std;
class MemberInitializationList
{
private:
int i;
int j;
public:
//*
MemberInitializationList(int val) : i(val), j(i)
{
}
//*/
/*
MemberInitializationList(int val)
{
i = val;
j = i;
}
//*/
inline void printInfo()
{
cout << "i = " << i << ", j = " << j << endl;
}
};
int main(void)
{
//cout << CLOCKS_PER_SEC << endl;
clock_t start = clock();
for(int i = 0; i < 3000000; i++)
{
MemberInitializationList* pMIL = new MemberInitializationList(i);
delete pMIL;
}
clock_t finish = clock();
cout << finish - start << " ms elapsed." << endl;
return 0;
}
结论:在VC6和VC2005的编译器上,两种方式似乎没有什么区别。或许在别的编译器上有所区别。也就是说,要么微软的编译器对于两种构造函数都使用了临时变量,或者都没有使用临时变量。
3)
调用一个成员函数设定成员变量的初值
#include <iostream>
#include <time.h>
using namespace std;
class MemberInitializationList
{
private:
int i;
int j;
public:
MemberInitializationList(int val)
: i(setI(val)), j(i) // 用成员函数设定成员变量的初始值也是可以的
{
}
inline int setI(int i)
{
return i;
}
inline void printInfo()
{
cout << "i = " << i << ", j = " << j << endl;
}
};
int main(void)
{
MemberInitializationList MIL(10);
MIL.printInfo();
return 0;
}
分享到:
相关推荐
关于“C++构造函数初始化列表 ”的实例分析
C++ Primer中在讲构造函数初始化列表的时候有这么一段话:无论是在构造函数初始化列表中初始化成员,还是在构造函数体中对它们赋值,最终结果是相同的。不同之处在于,使用构造函数初始化列表的版本初始化数据成员,...
讲解了为什么要初始化列表,初始化列表和在构造函数中赋值的区别
掌握C++初始化成员列表的相关用法,一般初学者对类的初始化列表总是很陌生.
matlab初始化数组
C++中,全局变量只能声明、初始化,而不能赋值 也就是说,下面这样是不被允许的: #include using namespace std; int a; a = 2; int main() { return 0; } 错误提示是: C++ requires a type specifier for all...
C++中成员初始化列表的使用 <br>适合初学者
今天小编就为大家分享一篇关于C++使用初始化列表的方式来初始化字段的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
EnumTest-初始化类的类成员对象(初始化列表方式)
c++初始化列表和构造函数初始化区别.pdf
下面小编就为大家带来一篇关于C++类的成员初始化列表的相关问题。小编觉得挺
何谓初始化列表与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。在C++中,struct和class的唯一区别是默认的克访问性不同...
使用初始化列表完成这步操作在性能上有益处。什么好处呢?摆道理显得不够彻底。看书不如做实验。让我们结合执行过程来查看。考虑如下示例代码: Derive 类构造函数两个 Base 类型的参数,分别赋给该类两个 ...
通常layui前端页面完全按照layui官网的例子写所有的页面初始化都没有问题,但是那只是静态页面.当加入后台去动态加载页面的时候有写样式在初始化加载样式的时候始终加载不上. 前端js拼接列表代码: 在这种情况下,你...
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如: class CExample { public: int a; float b; //构造函数初始化列表 CExample(): a(0...
初始化列表的例子.cpp
1.只能在构造函数初始化列表初始化的成员变量的类型? a.const成员变量 b.引用类型的成员变量 c.static不能在初始化列表中进行初始化 d.类成员变量中有自定义类型的变量最好在初始化列表中进行初始化 2.初始...
【Flutter】Dart 面向对象 ( 类定义 | 类的继承 | 私有变量 | 可选参数 | 默认参数 | 初始化列表 ) https://hanshuliang.blog.csdn.net/article/details/113735644 博客源码快照
主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。
oracle 初始化参数 的列表及说明