Questions:
(1)为什么需要在对象使用前初始化?
(2)关于默认构造函数的几点认识?
(3)为什么要使用参数初始化表进行初始化?
----------------------------------------------------------------------------------------------------------------------------------------------->
Answers:
(1)为什么需要在对象使用前初始化?
读取未初始化的值会导致不明确的行为,最终导致不可测试的程序结果,比如下面这个例子:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Point{
private:
int x, y;
public:
Point(){}
Point(int a, int b){
x = a;
y = b;
}
void print(){
cout<<"x = " << x << " y = " << y<<endl;
}
int getX(){
return x;
}
int getY(){
return y;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Point p;
p.print();
return 0;
}
输出结果为:
因此,要确保每一个构造函数都将对象的每一个成员初始化。
以上程序修改后为:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Point{
private:
int x, y;
public:
Point(){
x = 0;
y = 0;
}
Point(int a, int b){
x = a;
y = b;
}
void print(){
cout<<"x = " << x << " y = " << y<<endl;
}
int getX(){
return x;
}
int getY(){
return y;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Point p;
p.print();
return 0;
}
(2)关于默认构造函数的几点认识?
a.个类必须有一个构造函数,否则没法创建对象;
b.若程序没有提供任何构造函数,则C++提供一个默认的构造函数,该默认构造函数是无参构造函数,函数体为空,它仅负责创建对象,不做任何初始化的工作;
c.只要程序定义了一个构造函数(不管是无参还是有参构造),C++就不再提供默认的默认构造函数。即如果为类定义了一个带参的构造函数,还想要无参构造函数,就必须自己定义;
d.与变量定义类似,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0,否则,对象值是随机的。
(3)为什么要使用参数初始化表进行初始化?
C++引入构造函数的目的在于对变量的初始化做出强制,因为人们发现,程序的错误,很大程度上来说,都是由变量没有初始化造成的。
因此,一种很好的编程习惯就是,在定义变量的时候直接初始化。而在C++中,在变量定义时,系统会自动调用变量的构造函数对变量进行初始化。只要将相应的初始化代码放在构造函数中,就能够保证该类在实例化对象的时候能够给对象赋以理想的初值。
而事实远远没有这么简单。
C++规定:对象的成员变量的初始化动作发生在进入构造函数本体之前。初始化的发生时间是这些成员的default构造函数被自动调用之时。
实际上,程序在进入构造函数的大括号体时,就已经完成了变量的定义(也就是分配内存空间)。这就难免会造成这样的一种情况:在对象被构造时,程序进入构造函数大括号体之前,首先调用对象的default构造函数(进行初始化,即分配内存空间并赋初始值),然后进入构造函数体内,重新对变量进行赋值。这无疑降低了程序的效率。
看如下使用构造函数初始化的例子:
// InitializeTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <list>
using namespace std;
class PhoneNumber{
private:
string number;
public:
PhoneNumber(string number){
this->number = number;
}
};
class ABEntry
{
public:
ABEntry(){
theName = "abc";
theAddress = "abc";
numTimesConsulted = -1;
}
ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones){
theName = name;
theAddress = address;
thePhones = phones;
numTimesConsulted = 0;
}
private:
string theName;
string theAddress;
list<PhoneNumber> thePhones;
int numTimesConsulted;
};
int main(int argc, _TCHAR* argv[])
{
list<PhoneNumber> phones;
PhoneNumber number("1234567");
phones.push_back(number);
ABEntry abeEntry;
return 0;
}
我们在程序的第48行加上断点,然后进行单步调试,先调用无参构造函数ABEntry(),进入之后并不是先对大括号内的3个成员变量直接赋值,而是先调用default构造函数分别初始化4个成员变量(分配存储空间),初始化顺序与变量的声明顺序一致,即按照theName、theAddress、thePhone、numTimesConsulted的顺序分别调用string()、string()、list()进行初始化,因为numTimesConsulted是内置内型,所以不会进行初始化,执行这3个构造函数之后theName和theAddress的值都为“”,thePhone为null,这个过程结束之后才进入花括号内部,将实参的值分别赋给3个成员变量。所以整个过程包括初始化和复制两个过程,大大降低了效率。
因此,C++的设计者引入了构造函数初始化列表的概念。也就是说,在构造函数的初始化列表之中进行的是对变量的定义与初始化(分配内存空间),而不是简单的赋值。这样就能够解决上述的效率以及对构造函数的选择的问题。
// InitializeTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <list>
using namespace std;
class PhoneNumber{
private:
string number;
public:
PhoneNumber(string number){
this->number = number;
}
};
class ABEntry
{
public:
ABEntry():theName("abc"), theAddress("abc"), numTimesConsulted(0){}
ABEntry(const string& name, const string& address, list<PhoneNumber>& phones)
:theName(name), theAddress(address), thePhones(phones), numTimesConsulted(0){}
private:
string theName;
string theAddress;
list<PhoneNumber> thePhones;
int numTimesConsulted;
};
int main(int argc, _TCHAR* argv[])
{
list<PhoneNumber> phones;
PhoneNumber number("1234567");
phones.push_back(number);
ABEntry abeEntry("wanjun", "beijing", phones);
return 0;
}
该版本和上一个赋值的版本效果相同,但该版本的效率高。原因如下:
a.基于赋值的版本首先调用default构造函数为成员变量设初值,然后立刻在对他们赋予新值。
b.default构造函数的一切作为因此浪费了。
c.成员初始化列表避免了这一问题。
若想要default构造一个成员变量,也可以使用成员初始值列表,只要制定nothing做为初始化实参即可。如:
ABEntry::ABEntry()
:theName(), //call default constructor of theName
theAddress(), //do the same thing for theAddress
thePhones(), //do the same thing for thePhones
numTimesConsulted(0) explicit initialize the build-in type member 0
{
}
因为在初始化列表中发生的是成员变量的定义,也就是分配空间,因此初始化列表中构造的顺序与实际编译器定义变量的顺序可能是不一致的,也就是说,编译器不会按照设计者在初始化列表中初始化变量的顺序来为变量分配内存空间。初始化列表中变量的初始化顺序时其在类体内定义的顺序。
同样的,因为const型成员变量只能在被定义的同时被初始化而不能够再次被赋值,它也只能被放在构造函数的初始化列表中。
因此,C++的设计者引入了构造函数初始化列表的概念。也就是说,在构造函数的初始化列表之中进行的是对变量的定义与初始化(分配内存空间),而不是简单的赋值。这样就能够解决上述的效率以及对构造函数的选择的问题。
分享到:
相关推荐
《Effective Modern C++:改善C++11和C++14的42个具体做法(影印版)(英文版)》中包括以下主题:剖析花括号初始化、noexcept规范、完美转发、智能指针make函数的优缺点;讲解std∷move,std∷forward,rvalue引用和...
条款04:确定对象被使用前已先被初始化 2.构造/析构/赋值运算 条款05:了解C++默默编写并调用哪些函数 条款06:若不想使用编译器自动成生的函数,就该明确拒绝 条款07:为多态基类声明Virtual析构函数 条款08:...
Effective C++ 3rd Item 9 Effective C++ 3rd Item 9 Effective C++ 3rd Item 9 Effective C++ 3rd Item 9 Effective C++ 3rd Item 9
Effective C++:改善程序与设计的55个具体做法(中文第三版)亚马逊图书 放到Kindle上就可以浏览学习,因为亚马逊软件有防护功能,电脑上无法使用,切记!!!!
Effective C++跟more Effective c++
C++: Effective Modern C++ (C++ 11, C++ 14) (guide,C Programming, HTML, Javascript, Programming,all,internet, Coding, CSS, Java, PHP Vol 1) By 作者: Paul Laurence ISBN-10 书号: 1547133244 ISBN-13 书号:...
Effective C++(编程的50个细节) Effective C++(编程的50个细节)着重讲解了编写C++程序应该注意的50个...条款47:确保非局部静态对象在使用前被初始化 条款48:重视编译器警告 条款49:熟悉标准库 条款50:提高对C++的认识
电子版的effective c++ 和more effective c++ c++四书五经中介绍的经典书籍
学习C++ 和STL学习学习的书,三合一(共140种改善您的C++程序的经验之谈,C++程序员必读),英文原版,带书签,2018版本。难得的c++学习资料
effective c++ & more effective c++ 纯文字版
中文版 chm Effective C++ More effective C++
Effective C++ & More Effective C++.chm
Ruminations on C++),独沽一味者有之(Polymorphism in C++, Genericity in C++),独树一帜者有之(Design Patterns,Large Scale C++ Software Design, C++ FAQs),程式库大全有之(The C++ Standard Library)...
Effective c++.pdf Effective c++.pdf
effective c++ word版 effective c++ word版 effective c++ word版 effective c++ word版 effective c++ word版 effective c++ word版 effective c++ word版 effective c++ word版 effective c++ word版 effective ...
essential C++ & effective C++
More Effective C++ 35 New Ways to Improve Your Programs and Designs
Topics from the second edition have been extensively revised to reflect modern design considerations, including exceptions, design patterns, and multithreading.Important features of Effective C++ ...
effective C++,第一版和第二版是中文pdf,第三版是英文的pdf