C++初始化函数列表详细解析_C 语言

在以下三种情况下需要使用初始化成员列表:

一,需要初始化的数据成员是对象的情况;

二,需要初始化const修饰的类成员;

三,需要初始化引用成员数据;

原因:
C++可以定义引用类型的成员变量,引用类型的成员变量必须在构造函数的初始化列表中进行初始化。对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,(显然嘛,const就是防止被错误赋值的,引用类型必须定义赋值在一起),因此只能用初始化列表对齐进行初始化。成员类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。(也就是这三种情况必须使用初始化列表)

我们定义一个如下的Person类:

复制代码 代码如下:

class Person {

public:

  Person() { } //default constructor function

  Person(string name, string phone, string addr)

  {

    m_name = name; //想采用赋值初始化数据成员

    m_phone = phone;

    m_addr = addr;

  }

private:

  const string m_name;

  const string m_phone;

  const string m_addr;

};

编译后发现这个类的第二个带参数的构造函数是错误的。我们创建一个Person对象:

Person p("marcky", "13233232", "cqupt"); //调用带参数的构造函数创建一个Person对象 创建对象的过程分为了两步:

一、从内存中分配实际的空间给对象p,其三个字符串对象的数据成员是调用的默认构造函数初始化为空。也就说,此时为止,对象p的三个数据成员都是一个空的字符串。

二、执行调用的构造函数的函数体语句,完成对数据成员的赋值,以此达到我们期望的创建一个指定Person对象,而不是空对象。

从上面的第二步就可以看到,我们在对三个const对象进行赋值操作,这显然是不允许的操作,因此利用这个构造函数创建Person将以失败告终。要想成功的创建一个特定的Person对象,我们需要构造函数初始化列表:

Person(string name, string phone, string addr)
:m_name(name), m_phone(phone), m_addr(addr){ } //冒号开始定义初始化列表 使用初始化列表创建对象的构造函数同样是通过上述的两个步骤来完成的,不同之处在于创建对象的数据成员时使用的不是默认构造函数,而是根据指定参数调用了相应的构造函数,以此创建特定的对象,而不是空对象。这样一来,对象的数据成员的特定值在创建对象的时候就被赋予了相应的成员,而不是在创建对象完成之后再通过赋值语句去修改数据成员,因此利用构造函数初始化列表就可以成功的创建具有const数据成员的对对象了。

没有默认构造函数的类类型成员,如果不在初始化列表中初始化的话,那么创建该对象的时候,由于没有指定相应的“实参”,编译器就会去调用默认构造函数来创建对象,必然会以失败而告终。

注1:数据成员被初始化的顺序与构造函数初始化列表中的次序无关,而是与成员的定义顺序一致。

注2:使用初始化列表效率更高,如果在构造函数中赋值则是拷贝,如果是初始化列表中则是初始化,赋值和初始化当然效率不一样了。

时间: 2024-10-23 10:53:52

C++初始化函数列表详细解析_C 语言的相关文章

C语言文件操作函数freopen详细解析_C 语言

今天做USACO  用到了文件的操作. 之前做USACO只是格式化的些 写  freopen("xxx.in","r",stdin)  和"freopen("xxx.out","w",stdout)"  百度百科上是这么介绍的: 函数名: freopen 功 能: 替换一个流,或者说重新分配文件指针,实现重定向.如果stream流已经打开,则先关闭该流.如果该流已经定向,则freopen将会清除该定向.此函

C++中的friend函数详细解析_C 语言

为什么要使用友元函数 在实现类之间数据共享时,减少系统开销,提高效率.如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数.具体来说:为了使其他类的成员函数直接访问该类的私有变量.即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数. 实际上具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些场合需要使用友元.(2)两个类要共享数据的时候. 使用友元函数的优缺点 优点:能够提高效率,表达简单.清晰. 缺点:友元函数破环

VC中Tab control控件的用法详细解析_C 语言

1. 新建一个MFC工程, 取名MyTab, 选择Dialog based, 然后Finish. 2. 删除对话框上默认添加的三个控件. 添加Tab Control控件并在Property属性中设置ID为IDC_TABTEST 在More Styles里勾上Bottom. 调速尺寸使其布满整个对话框, 我这边Tab Control的尺寸最后为164X203. 在ClassWizard为其添加变量, 变量名为m_tab. 类型为CTabCtrl. 3. 在对话框的初始化函数OnInitDialog

成员初始化列表与构造函数体中的区别详细解析_C 语言

论坛中回答一个别人问题 C++ Primer中在讲构造函数初始化列表的时候有这么一段话:无论是在构造函数初始化列表中初始化成员,还是在构造函数体中对它们赋值,最终结果是相同的.不同之处在于,使用构造函数初始化列表的版本初始化数据成员,没有定义初始化列表的构造函数版本在构造函数体中对数据成员赋值. 请问这里的初始化数据成员与对数据成员赋值的含义是什么?有什么区别? 我知道在数据成员有默认构造函数时是有不同的,但对其他类型的成员呢?其他类型成员的初始化和赋值有区别吗?================

函数外初始化与函数内初始化详细解析_C 语言

关于函数外初始化与函数内初始化之前一直分的不是太清,也不太在意.昨天终于出现了这方面的问题,所以决定好好看下,以下是这次的一些收获,先看测试代码: 复制代码 代码如下: #include "stdafx.h"#include <iostream>using namespace std;bool FillStr(char *&szDst, int nSize){ bool bRet = false; if (nSize > 0) {  szDst = (char

C语言中的内联函数(inline)与宏定义(#define)详细解析_C 语言

先简明扼要,说下关键:1.内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快. 2.内联函数可以调试,而宏定义是不可以调试的.内联函数与宏本质上是两个不同的概念如果程序编写者对于既要求快速,又要求可读的情况下,则应该将函数冠以inline.下面详细介绍一下探讨一下内联函数与宏定义. 一.内联函数是什么?内联函数是代码被插入到调用者代码处的函数.如同 #define 宏(但并不等同,原因见下文),内联函数通过避免被调用的开销来提

C++指向类成员函数的指针详细解析_C 语言

首先 函数指针是指向一组同类型的函数的指针:而类成员函数我们也可以相似的认为,它是指向同类中同一组类型的成员函数的指针,当然这里的成员函数更准确的讲应该是指非静态的成员函数.前者是直接指向函数地址的,而后者我们从字面上也可以知道 它肯定是跟类和对象有着关系的. 函数指针实例: 复制代码 代码如下: typedef int (*p)(int,int);//定义一个接受两个int型且返回int型变量的函数指针类型int func(int x,int y){ printf("func:x=%d,y=%

C++中函数模板的用法详细解析_C 语言

定义 我们知道函数的重载可以实现一个函数名多用,将功能相同或者类似函数用同一个名来定义.这样可以简化函数的调用形式,但是程序中,仍然需要分别定义每一个函数. C++提供的函数模板可以更加简化这个过程. 所谓函数模板实际上是建立一个通用函数,其涵涵素类型额形参类型不具体指定,用一个虚拟的类型来代表,这个通用函数就称为函数模板. 凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需要在模板中定义一次即可.在调用函数时,系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能

C++中函数的默认参数详细解析_C 语言

使用方法:(1)在函数声明或定义时,直接对参数赋值,该参数就是默认参数.(2)在函数调用时,省略部分或全部参数,这时就会使用默认参数进行代替. 注意事项:(1)一般在声明函数是设置默认参数. 如果在函数声明和定义函数时都设置了默认参数,则以函数声明的默认参数为准. 复制代码 代码如下: #include<iostream>using namespace std;int main(){ double add(double a=3.2,double b=9.6);//在函数声明时设置默认参数 co