20160403_C++初始化列表与赋值

引用自:http://www.cnblogs.com/BlueTzar/articles/1223169.html

1. 两种初始化方式:构造函数初始化列表 和 构造函数内部赋值

(1) 构造函数初始化列表

  构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。

class CExample {
public:
    int a;
    float b;
    // 构造函数初始化列表
    CExample(): a(0),b(8.8)
    {    // a赋值为0,b赋值为8.8   }
};
(2) 构造函数内部赋值
class CExample {
public:
    int a;
    float b;
    //构造函数内部赋值
    CExample()
    {
        a=0;
        b=8.8;
    }
};
(3)两种初始化方式的比较:
  • 上面的例子中两个构造函数的结果是一样的。上面的构造函数(使用初始化列表的构造函数)显式的初始化类的成员;而没使用初始化列表的构造函数是对类的成员赋值,并没有进行显式的初始化。
  • 初始化和赋值对内置类型的成员没有什么大的区别,像上面的任一个构造函数都可以。对非内置类型成员变量,为了避免两次构造,推荐使用类构造函数初始化列表。但有的时候必须用带有初始化列表的构造函数:
    1.成员类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。
    2.const成员或引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值。
  • 初始化数据成员与对数据成员赋值的含义是什么?有什么区别?
    首先把数据成员按类型分类并分情况说明:
    1.内置数据类型,复合类型(指针,引用)
        在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
    2.用户定义类型(类类型)
        结果上相同,但是性能上存在很大的差别。因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)

2. 初始化列表的成员初始化顺序

C++初始化类成员时,是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。
  Example:

class CMyClass {
    CMyClass(int x, int y);
    int m_x;
    int m_y;
};

CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y)
{
}

  你可能以为上面的代码将会首先做m_y=I,然后做m_x=m_y,最后它们有相同的值。

  但是编译器先初始化m_x,然后是m_y,,因为它们是按这样的顺序声明的。结果是m_x将有一个不可预测的值。有两种方法避免它,一个是总是按照你希望它们被初始化的顺序声明成员,第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。

3. 例题

  如下代码,result变量的输出结果是多少?

#include<iostream>
using namespace std;
int i=1;
class MyCls{
public:
    MyCls():m_nFor(m_nThd),m_nSec(i++),m_nFir(i++),m_nThd(i++){
        m_nThd=i;
    }
    void echo(){
        cout<<"result:"<<m_nFir+m_nSec+m_nThd+m_nFor<<endl;
    }
private:
    int m_nFir;
    int m_nSec;
    int m_nThd;
    int &m_nFor;
};
int main()
{
    MyCls oCls;
    oCls.echo();
    return 0;
}

解答:

  首先要明白变量初始化的顺序是其声明的顺序,跟初始化列表中的顺序无关。所以变量的初始化顺序为m_nFir(i++),m_nSec(i++),m_nThd(i++),&m_nFor(m_nThd);

  i初始值为1,所以经过初始化列表初始化以后:
  •   m_nFir(i++)使用i赋值为1,之后i自加为2
  • m_nSec(i++)使用i赋值为2,之后i自加位3
  •   m_nThd(i++)使用i赋值为3,之后i自加位4
  • m_nFir=1,m_nSec=2,m_nThd=3,m_nFor为m_nThd的一个引用

      并且此时i的值为4,构造函数中执行语句m_nThd=i后,m_nThd=4,m_nFor是它的一个引用,自然值也为4。

      输出结果m_nFir+m_nSec+m_nThd+m_nFor=1+2+4+4=11

 
时间: 2024-11-06 23:10:24

20160403_C++初始化列表与赋值的相关文章

C++构造函数初始化列表与赋值

C++中类的初始化操作一般有四个部分组成: 1.构造函数初始化列表 2.构造函数体内赋值 3.类外部初始化 4.类声明时直接赋值 对于内部数据类型(char,int,float...),构造函数初始化列表和构造函数体内赋值,基本上没多大区别,效率差异也不大,但两者不能共存: class Student { public: Student(char *name, int age): //A初始化列表 m_name(name), m_age(age) { } Student(char *name,

C++中构造函数初始化列表为什么会比构造函数中赋值要高效

Test { Test(test& t1) { this->t=t1; } private: test t; } 相信很多人跟我一样,非常困惑为什么Test构造时会先调用test的构造函数,再调用test类的赋值操作符.那是因为赋值操作符不能产生新的对象,Test构造时免不了要构造一个test对象.所以正常流程是 先构造t,然后再调用赋值操作符赋值t(this->t=t1). 如果写成 Test { Test(test& t1):t(t1) { } private: test

c++初始化列表

何谓初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段.在C++中,struct和class的唯一区别是默认的访问性不同,而这里我们不考虑访问性的问题,所以下面的代码都以struct来演示. struct foo { string name ; int id ; foo(string s, int i):name(s), id(i){} ; // 初始化列表 }; 构造函数的两个执行阶段 构造函数的执行

C++使用初始化列表提高效率(转):

转自:http://www.cnblogs.com/graphics/archive/2010/07/04/1770900.html 何谓初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段.在C++中,struct和class的唯一区别是默认的访问性不同,而这里我们不考虑访问性的问题,所以下面的代码都以struct来演示. struct foo { string name ; int id ; foo(

C++ 初始化列表(一)

何谓初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表.初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段.在C++中,struct和class唯一的区别就是struct的所有成员默认都是public的,所以如果不考虑成员的可访问性,这两者是没有区别的,而这里我们不考虑访问性的问题,所以下面的代码都以struct来演示. struct foo { string name ; int id ; foo(string s, int i):name(s), i

【校招面试 之 C++】第1题 为什么优先使用构造函数的初始化列表

1.首先看一个例子: #include<iostream> using namespace std; class Test1 { public: Test1() // 无参构造函数 { cout << "Construct Test1" << endl ; } Test1(const Test1& t1) // 拷贝构造函数 { cout << "Copy constructor for Test1" <

C++构造函数对类成员变量初始化,使用初始化列表和构造函数内部直接赋值 的差别

初始化和赋值对内置类型的成员没有什么大的差别,像任一个构造函数都能够. 但有的时候必须用带有初始化列表的构造函数: (1) 成员类型是没有默认构造函数的类.若没有提供显式初始化时,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败. (2) const成员或引用类型的成员.由于const对象或引用类型仅仅能初始化,不能对他们赋值. 另一个赋值次数,效率上的差别: 初始化參数列表在对象初始化时对成员变量赋值一次. 构造函数内直接赋值,对成员变量赋值两

C++有哪几种情况只能用初始化列表,而不能用赋值?

原文链接:http://blog.csdn.net/yuliu0552/article/details/6631509   C++有哪几种情况只能用初始化列表,而不能用赋值? (1)对于const和reference类型成员变量,它们只能够被初始化而不能做赋值操作,因此只能用初始化列表; 初始化与赋值是不同的:赋值是删除原值,赋予新值,构造函数的意思是先开辟空间然后为其赋值,只能算是赋值,不算初始化: 初始化列表就不一样了,开辟空间和初始化是同时完成的,直接给予一个值: 常量不能被赋值,只能被初

构造函数初始化列表和构造函数体内赋值

#include <iostream> using namespace std; class A{ public: A(int a,string str) { m_a = a; m_str = str; } //A(int a,string str):m_a(a),m_str(str){} void print() { cout << m_a << ' '<< m_str<< endl; } private: int m_a; string m_