- 浏览: 428303 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
su6838354:
我有点疑问啊,thread1中的i自增的慢的话,thread2 ...
浅析pthread_cond_wait -
zeronever:
请问pthread_cond_signal有解锁操纵吗?我在p ...
浅析pthread_cond_wait -
paladin1988:
你这帖子真心不错。。
浅谈bitmap算法 -
parabellum_sky:
昨天还有个姑娘让我去考我说会考虑
个人日志
最近看C++方面的书,让我更深入的理解了C++的构造函数。什么情况下调用默认构造函数,什么情况下调用拷贝构造函数以及什么情况下使用显示的初始化列表,初始化列表的初始化顺序,以及显示的初始化列表和拷贝构造函数的区别,为什么拷贝构造函数和赋值构造函数同时出现?
1.默认构造函数
如果我们没有定义自己的构造函数,编译时会自动调用默认构造函数来初始化类的对象。那么既然可以调用默认的构造函数,为何还要自己定义构造函数?我的理解是:如果想初始化类的数据成员为某些特定的值时,这时就需要自己定义构造函数,否则不需要。
2.拷贝构造函数
既然有自己定义的构造函数,为何还要用拷贝构造函数。但是当类的数据成员包含指针,即需要动态的申请内存时,这是就需要自己定义拷贝构造函数。因为如果没有拷贝构造函数动态的为每一个对象申请内存,而只是用默认的拷贝构造函数来初始化类的对象时,所有的类的对象的指针数据成员所指向的是同一块地址,也就是不同的指针但是指向的却是同一块内存,而没有开辟自己的内存,这样在程序结束时调用析构函数就会出现一个内存块多次释放的错误。
比如下面的例子:
Matrix a(4,6);利用自定义的构造函数初始化对象a,并为double*_pmat;动态申请了内存。
Matrix b = a;由于programm没有定义自己的拷贝构造函数,编译器会使用默认的拷贝构造函数,int _row, _col; 都可以恰当的被初始化,可是double *_pmat; 的初始化就不同了,只是b._pmat = a._pmat,这样a._pmat和b._pmat指向同一块内存。当然他们在使用的时候没有问题,但是当编译器调用析构函数~Matrix() 时就会出现问题,先是b.~Matrix() 这是已经把a对象申请的地址释放了,但当调用a.~Matrix() 时,就会出现问题。
拷贝构造函数如何定义:
类名::类名(const 类名 & 对象)
{
}
例如:
3.拷贝赋值构造函数
为何要使用赋值构造函数,已经有了默认构造函数、自定义构造函数、拷贝构造函数,为何还要拷贝构造函数。类也是一种类型,类似于int char,为了兼容C中的赋值操作符,比如 int a = 2.;int b; b = a; 类的对象也可以直接赋值,这就是赋值构造函数的作用。
但是赋值构造函数也有默认的构造函数,为何不用默认的构造函数,这个原因和拷贝构造函数类似,也是当类的成员函数需要动态申请内存时就需要使用自定义的赋值构造函数。
赋值构造函数如何定义:
类名 & 类名::operator=(const 类名 & rhs)
{
}
4.构造函数初始化列表
为何要使用初始化列表,直接在构造函数体内初始化数据成员不也一样吗?
构造函数初始化列表也成为显示的初始化数据成员,它不需要隐士的调用拷贝构造函数直接初始化,效率会高些,而在构造函数体内初始化数据成员则会隐士调用拷贝构造函数,效率会低些。
1.默认构造函数
如果我们没有定义自己的构造函数,编译时会自动调用默认构造函数来初始化类的对象。那么既然可以调用默认的构造函数,为何还要自己定义构造函数?我的理解是:如果想初始化类的数据成员为某些特定的值时,这时就需要自己定义构造函数,否则不需要。
2.拷贝构造函数
既然有自己定义的构造函数,为何还要用拷贝构造函数。但是当类的数据成员包含指针,即需要动态的申请内存时,这是就需要自己定义拷贝构造函数。因为如果没有拷贝构造函数动态的为每一个对象申请内存,而只是用默认的拷贝构造函数来初始化类的对象时,所有的类的对象的指针数据成员所指向的是同一块地址,也就是不同的指针但是指向的却是同一块内存,而没有开辟自己的内存,这样在程序结束时调用析构函数就会出现一个内存块多次释放的错误。
比如下面的例子:
class Matrix { public: Matrix( int row, int col ) : _row( row ), _col( col ) { // constructor allocates a resource // note: no error checking is shown _pmat = new double[ row * col ]; } ~Matrix() { // destructor frees the resource delete [] _pmat; } // ... private: int _row, _col; double *_pmat; }; int main() { Matrix a(4,6); Matrix b = a; return 0; }
Matrix a(4,6);利用自定义的构造函数初始化对象a,并为double*_pmat;动态申请了内存。
Matrix b = a;由于programm没有定义自己的拷贝构造函数,编译器会使用默认的拷贝构造函数,int _row, _col; 都可以恰当的被初始化,可是double *_pmat; 的初始化就不同了,只是b._pmat = a._pmat,这样a._pmat和b._pmat指向同一块内存。当然他们在使用的时候没有问题,但是当编译器调用析构函数~Matrix() 时就会出现问题,先是b.~Matrix() 这是已经把a对象申请的地址释放了,但当调用a.~Matrix() 时,就会出现问题。
拷贝构造函数如何定义:
类名::类名(const 类名 & 对象)
{
}
例如:
Matrix::Matrix( const Matrix &rhs ) : _row( rhs._row ), _col( rhs._col ) { // create a "deep copy" of the array addressed by rhs._pmat int elem_cnt = _row * _col; _pmat = new double[ elem_cnt ]; for ( int ix = 0; ix < elem_cnt; ++ix ] //动态申请内存 _pmat[ ix ] = rhs._pmat[ ix ]; }
3.拷贝赋值构造函数
为何要使用赋值构造函数,已经有了默认构造函数、自定义构造函数、拷贝构造函数,为何还要拷贝构造函数。类也是一种类型,类似于int char,为了兼容C中的赋值操作符,比如 int a = 2.;int b; b = a; 类的对象也可以直接赋值,这就是赋值构造函数的作用。
但是赋值构造函数也有默认的构造函数,为何不用默认的构造函数,这个原因和拷贝构造函数类似,也是当类的成员函数需要动态申请内存时就需要使用自定义的赋值构造函数。
赋值构造函数如何定义:
类名 & 类名::operator=(const 类名 & rhs)
{
}
Matrix& Matrix:: operator=( const Matrix &rhs ) { if ( this != &rhs ) //防止自符值 { _row = rhs._row; _col = rhs._col; int elem_cnt = _row * _col; delete [] _pmat; _pmat = new double[ elem_cnt ]; for ( int ix = 0; ix < elem_cnt; ++ix ] _pmat[ ix ] = rhs._pmat[ ix ]; } return *this; };
4.构造函数初始化列表
为何要使用初始化列表,直接在构造函数体内初始化数据成员不也一样吗?
构造函数初始化列表也成为显示的初始化数据成员,它不需要隐士的调用拷贝构造函数直接初始化,效率会高些,而在构造函数体内初始化数据成员则会隐士调用拷贝构造函数,效率会低些。
发表评论
-
Google编程风格
2012-04-01 17:05 1067Google编程风格(自己整 ... -
VS2008快捷键的设置
2012-02-02 13:43 2601VS2008快捷键的设置 VS2008默认的快捷键和VC++ ... -
LINK : fatal error LNK1000: Internal error during IncrBuildImage
2011-12-16 17:07 1177Win7安vc2008编译报LINK : fatal erro ... -
volatile关键字(摘自:百度百科)
2011-12-16 14:59 691volatile关键字[align=center][/alig ... -
InterlockedIncrement
2011-12-16 14:44 2139InterlockedIncrement[align=cent ... -
关键词explicit
2011-12-10 20:32 814关键词explicit[size=large][/size][ ... -
Souce Insight 设置
2011-12-09 17:16 1944Souce Insight 设置 【问题】 Source I ... -
VS2008下Boost库的安装编译下载boost库
2011-11-09 19:19 2001下载boost库 (最好去官网下,一般有SGI(GCC+用的较 ... -
C++多态技术的实现和反思(转)
2011-10-17 17:05 765面向对象技术最早出现于1960年代的Simula 67系统,并 ... -
memmove and memcpy
2011-07-31 13:11 1143memmove and memcpy 字符串的拷贝函数mem ... -
Polymorphism & Virtual Function
2011-07-25 21:38 817Polymorphism & Virtual Func ... -
C++ 不要重新定义继承的非虚函数
2011-07-18 14:15 1261不要重新定义继承的非虚函数 如果基类和派生类有相同的非虚函数 ... -
C++ 虚函数表解析
2011-07-14 21:02 940C++ 虚函数表解析 为什么在C++机制里要有虚函数表?虚函 ... -
C++ 默认构造函数
2011-07-14 11:39 3681C++ 默认构造函数 一直 ... -
尽量使用const
2011-07-12 10:51 1073尽可能的使用const const: ... -
Operator=
2011-07-11 21:54 905Operator= 赋值构造函数 ... -
虚析构函数
2011-07-11 10:43 1128虚析构函数 一 、为何要单独讨论虚析构函数?虚函数在类中到底 ... -
初始化列表和声明顺序之间的关系
2011-07-11 09:18 1436初始化列表和声明的顺序之间的关系 类中数据成员的声明顺序和初 ... -
初始化函数列表和构造函数内赋值之区别
2011-07-10 17:05 4459初始化函数列表和构造 ... -
传值和传引用的区别
2011-07-10 15:30 2337传值和传引用的区别 在C语言中,大都是通过值传递,C++也是 ...
相关推荐
关于“C++构造函数初始化列表 ”的实例分析
C++构造函数,拷贝构造函数,虚函数,派生类
重载构造函数,调用成员函数,供C++初学者理解构造函数重载的概念
C++构造函数分类讲解,常见的构造函数都有讲解,虽然讲解的不是很详细但是能有利于新手的记忆。
这是课上用的quiz,c++语法,关于什么情况下会调用什么构造函数
C++构造函数,复制构造函数和析构函数专题[1].pdf C++继承,虚函数与多态性专题.pdf
C++构造函数详解及显式调用构造函数.doc
我刚学C++构造函数与析构函数,现在自己写了一段代码,和你们分享
C++构造函数.pdf
C++构造函数、复制构造函数和析构函数专题(修订版).pdf
2.1深入C++构造函数共3页.pdf.zip
C++构造函数和析构函数的调用顺序举例一.调用方法和区别1、构造函数的调用顺序: 基类构造函数、对象成员构造函数、派生类本身的构造函数 2、析构函数的调用顺序:
C++构造函数、复制构造函数和析构函数专题(修订版)[汇编].pdf
C++构造函数_析构函数和赋值操作符学习小结
C++构造函数与析构函数.pdf
本程序包含构造函数和析构函数,可以把构造函数和析构函数的作用区分开
c++中关于构造函数与析构函数部分的课件,有助于初学者自学。
C++构造函数[定义].pdf