构造函数初始化

参考:c++ primer p385

构造函数的名字与类的名字相同,且不能返回指定类型

构造函数可以被重载,只要构造函数的形参表是唯一的

构造函数初始化有两种方式,一种是使用初始化列表,一种是在构造函数的函数体内对数据成员赋值

初始化列表:

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

Sales_item::Sales_item(const string &book):
isbn(book), units_sold(0), revenue(0.0) { }

函数体内初始化:

可以认为构造函数分为两个执行阶段:(1)初始化阶段(2)普通的计算阶段,计算阶段由构造函数函数体中的所有语句组成

Sales_item::Sales_item(const string &book)
{
    isbn = book;
    units_sold = 0;
    revenue = 0.0;
}

区别和选择: 

无论是在构造函数初始化列表中初始化成员,还是在构造函数函数体中对它们赋值,最终结果是相同的。不同之处在于,使用构造函数初始化列表的版本初始化数据成员,没有定义初始化列表的构造函数版本在构造函数函数体中对数据成员赋值。 这个区别的重要性取决于数据成员的类型。

1.内置数据类型,复合类型(指针,引用)
在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
2.用户定义类型(类类型)
结果上相同,但是性能上存在很大的差别。因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)

class Test4 {
public:
    Test3 t3;
    //Test4( Test3 &t3) : t3(t3) { //这种方式和下面的方式有相同的效果,不同的效率
    //}
    Test4( Test3 &t3) {
        this->t3 = t3;
    };
}; 

在许多类中,初始化和赋值严格来讲都是低效率的:数据成员可能已经被直接初始化了, 还要对它进行初始化和赋值。 比效率问题更重要的是,某些数据成员必须要初始化,这是一个事实。

必须对任何 const 或引用类型成员以及没有默认构造函数的类类型的任何成员使用初始化式。

class ConstRef {
public:
    ConstRef(int ii);
private:
    int i;
    const int ci;
    int &ri;
};

ConstRef::ConstRef(int ii)
{ // assignments:
    i = ii; // ok
    ci = ii; // error: cannot assign to a const
    ri = i; // assigns to ri which was not bound to an object
}

ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }

成员初始化的次序

成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的

struct foo
{
    int i ;
    int j ;
    foo(int x):i(x), j(i){}; // ok, 先初始化i,后初始化j
};

再看下面的代码

struct foo
{
    int i ;
    int j ;
    foo(int x):j(x), i(j){} // i值未定义
};

这里i的值是未定义的因为虽然j在初始化列表里面出现在i前面,但是i先于j定义,所以先初始化i,但i由j初始化,此时j尚未初始化,所以导致i的值未定义。所以,一个好的习惯是,按照成员定义的顺序进行初始化

时间: 2024-12-29 07:52:39

构造函数初始化的相关文章

构造函数初始化器

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 {     class Program     {         static void Main(string[] args)         {             cat c = new cat(

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,

const成员或者引用成员必须使用构造函数初始化列表的方式

#include<iostream.h> class A { const int a; int b; }; void main() { A obja; }编译出现如下错误:error C2512: 'A' : no appropriate default constructor available;如果将const去掉就没错了! #include<iostream.h> class A { public: const int a; int b; A(int x):a(x){} };

构造函数初始化语句!!!

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace nange_1 { class A { readonly int Amyint_1 = 3; readonly int Amyint_2 = 4; public string name; public int age; private A() //私有构造函数执行其他构造 { //函数共用的初始化 Amyi

构造函数初始化列表

构造函数初始化列表有时是必要的.虽然构造函数分为初始化和计算阶段,使用初始化构造函数列表效率要高一些,这是其一,而且有些情况下必须使用,下面是一例, 1 class Foo 2 { 3 public: 4 Foo(int x, int y): a(x), b(y) {} 5 6 private: 7 int a; 8 int b; 9 }; 10 11 class Bar 12 { 13 public: 14 Bar(): foo(10, 10) {} 15 private: 16 Foo fo

[c++基本语法]——构造函数初始化列表

c++构造函数初始化成员变量列表: 1 #pragma once 2 class Node 3 { 4 public: 5 int data; // 权值 6 Node *parent; // 父节点 7 Node *left; // 左子节点 8 Node *right; // 右子节点 9 public: 10 // 该段代码是c++的基本语法中的“构造函数初始化成员变量列表” 11 Node(void):data(-1),parent(NULL),left(NULL),right(NULL

使用构造函数初始化三角形类

方法1:使用带参数构造函数,即Triangle(double x, double y, double z),三边长在调用时由实参直接给出 #include <iostream> #include <cmath> using namespace std; class Triangle { public: //带参构造函数 Triangle(double x, double y, double z); double perimeter(void);//计算三角形的周长 double a

使用构造函数初始化成员数组

#include <iostream> using namespace std; class Box//盒子类 { public: //定义一个构造函数用于初始化对象数组 Box(int h, int w, int l); int volume();//计算盒子的体积 private: int height;//盒子的高 int width;//盒子的宽 int length;//盒子的长 }; //定义一个构造函数用于初始化对象数组 Box::Box(int h, int w, int l)

转:C++类构造函数初始化列表

构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample { public:     int a;     float b;     //构造函数初始化列表     CExample(): a(0),b(8.8)     {}     //构造函数内部赋值     CExample()     {         a=0;         b=8.8;     } }; 上面的例子中两个构造函数的结果是一样