C++中构造函数初始化列表与构造函数体的区别

news/2024/5/18 22:44:28 标签: 构造函数, 初始化函数列表, 函数体, 赋值

既然构造函数初始化列表和构造函数体内赋值都可以对成员变量赋值,那么二者有何区别,是不是二者等效呢? 


构造函数可以分两个阶段进行:(1)初始化阶段;(2)普通计算阶段。计算阶段也就是由函数体内所有的语句组成。不管成员是否在构造函数初始化列表中显式初始化,类的数据成员初始化总是在初始化阶段进行,初始化阶段先于计算阶段。构造函数初始化列表是对类的成员做初始化,而在构造函数体内只是对类的数据成员进行了一次赋值操作。

构造函数初始化列表只是指定了成员的初始值,并没有指定初始化顺序,那么成员初始化顺序又是怎样的呢?成员的初始化顺序就是定义成员的顺序,第一个定义的成员首先被初始化,然后是第二个等等。


一、若类的数据成员是静态的(const)和引用类型,必需用初始化列表 

静态(const)的数据成员只能初始化而不能赋值,同样引用类型也是只可以被初始化,那么只有用初始化列表。 

如: 
C++代码   收藏代码
  1. #include <iostream>  
  2. #include <string>  
  3. using namespace std;  
  4.   
  5. template<class t>  
  6. class namedptr {  
  7. public:  
  8.     namedptr(const string& initname, t *initptr);  
  9. private:  
  10.     const string name; //静态数据成员的初始化必需用初始化列表  
  11.     t * const ptr;  
  12. };  
  13.   
  14.   
  15.   
  16. template<class t>  
  17. namedptr<t>::namedptr(const string& initname, t *initptr  )  
  18. : name(initname), ptr(initptr)  
  19. {}  
  20.   
  21. //第二种方法是在构造函数体内赋值  
  22.   
  23. //template<class t>  
  24. //namedptr<t>::namedptr(const string& initname, t *initptr)  
  25. //{  
  26. //  name = initname;  
  27. //  ptr = initptr;  
  28. //}  
  29.   
  30.   
  31. int main()  
  32. {  
  33.     int a  = 10;  
  34.     namedptr<int> Test("SHENZHEN",&a);  
  35. }  

由于 const string name; //静态数据成员的初始化必需用初始化列表 
t * const ptr; 
是静态的,如果用构造函数体内赋值,编译会出错。 

二、构造函数体内赋值会带来额外的开销,效率会低于构造函数初始化列表 

上面的例子改一改: 

C++代码   收藏代码
  1. template<class t>  
  2. class namedptr {  
  3. public:  
  4.     namedptr(const string& initname, t *initptr);  
  5. private:  
  6.     string name; //静态数据成员的初始化必需用初始化列表  
  7.     t * ptr;  
  8. };  


并且用这两中初始化方法做对比: 
C++代码   收藏代码
  1. //第一种方法:初始化列表  
  2. template<class t>  
  3. namedptr<t>::namedptr(const string& initname, t *initptr  )  
  4. : name(initname), ptr(initptr)  
  5. {}  
  6.   
  7. //第二种方法是在构造函数体内赋值  
  8.   
  9. template<class t>  
  10. namedptr<t>::namedptr(const string& initname, t *initptr)  
  11. {  
  12.     name = initname;  
  13.     ptr = initptr;  
  14. }  


当用第二种方法初始化数据成员时会两次对string的成员函数的调用:一次是缺省构造函数,另一次是赋值。 

而用第一种方法(初始化列表)只是一次调用缺省的构造函数,并不会调用赋值函数。会减少不必要的开支,当类相当复杂时,就会看出使用初始化列表的好处。 


http://www.niftyadmin.cn/n/1437403.html

相关文章

好莱坞八大影业公司

好莱坞八大影业公司 主要包括&#xff1a;华纳兄弟公司、米高梅电影公司、派拉蒙影业公司、哥伦比亚影业公司、环球电影公司、联美电影公司、20世纪福克斯、迪士尼电影 。 1米高梅 简介 米高梅 Metro-Goldwyn-Mayer (MGM)好莱坞五大电影公司之一。 一个电影…

Qt连接MySQL

一般情况下&#xff0c;qt只带了qsqlite4和qodbc两种驱动&#xff0c;如果在安装qt时&#xff0c;你没有添加qt -mysq参数&#xff0c;那么意味着&#xff0c;在你的程序中不能直接使用mysql数据库。 那么你就需要安装这个插件。 感谢jpzjpz提供的详细安装过程&#xff01; 网址…

Kafka分布式消息队列(一):基础

本文基于Kafka 0.8 1. 引言 Kafka是LinkedIn开发并开源出来的一个高吞吐的分布式消息系统。其具有以下特点&#xff1a; 1) 支持高Throughput的应用 2) scale out&#xff1a;无需停机即可扩展机器 3) 持久化&#xff1a;通过将数据持久化到硬盘以及replication防止数据丢失 …

Kafka分布式消息队列(二):环境搭建测试

本文基于Kafka 0.8 在一台机器上构建一个3个节点的kafka集群&#xff0c;并测试producer、consumer在正常情况下的行为&#xff0c;以及在lead broker/follow broker失效情况下的行为1.下载并解压kafka 0.8.0 release$ mkdir kafka$ wget http://apache.dataguru.cn/kafka/0.8.…

Linux的零拷贝技术(zero-copy)

1. 使用直接 I/O 的数据传输 如果应用程序可以直接访问网络接口存储&#xff0c;那么在应用程序访问数据之前存储总线就不需要被遍历&#xff0c;数据传输所引起的开销将会是最小的。应用程序或 者运行在用户模式下的库函数可以直接访问硬件设备的存储&#xff0c;操作系统内核…

C++的const类成员函数

我们知道&#xff0c;在C中&#xff0c;若一个变量声明为const类型&#xff0c;则试图修改该变量的值的操作都被视编译错误。例如&#xff0c; [cpp] view plaincopyconst char blank ‘’; blank ‘\n’; // 错误 面向对象程序设计中&#xff0c;为了体现封装性&#x…

腾讯面试

1. 笔试 1.1 char p[][10] {"hello", "world"}; q p[0]; q q 10; 求strlen(q)? 1.2 网络数字签名是什么&#xff1f; 1.3 考查sizeof&#xff0c;比如&#xff1a; int main() { char str[] "hello"; char *p "hello"; size…

序列平衡点

题目一&#xff1a; 一个序列的平衡点是这样的&#xff0c;它的左边的所有的元素的和应该等于右边的所有的元素的和&#xff0c;比如在下面的序列A&#xff1a; A[0] -7 A[1] 1 A[2] 5 A[3] 2 A[4] -4 A[5] 3 A[6] 03是一个平衡点因为: A[0] A[1] A[2] A[4] A[5] …