turingwy

C++中的拷贝构造函数

C++中对象由于既有在堆栈中又有在堆中,导致了类的构造函数种类繁多

而在java中在堆栈中只有对象的引用,所以使用起来非常简单,易于上手。


本文主要记录我在学习中对C++拷贝构造函数的认识。


在C++ Primer书中,作者把这些构造函数的章节放到后边,而先将了STL中的内容,而这里面又经常出现拷贝构造函数,所以我特地记录一下这类构造函数的要点。


在C++ Primer一书中,拷贝构造函数在使用的时候其实就像内置类型的拷贝初始化。

这里先提一下什么是内置类型的拷贝初始化

内置类型就是int,char,short,lang,lang lang,double,float,bool这几个,除了bool都是继承自C语言,C语言中对这些类型的初始化和赋值都使用一种方式——等号。例如 int a = 13;

这种方式在C++中就叫做拷贝初始化,在C++中不仅仅有这一种方式,还可以使用小括号,大括号,以及等号大括号,这些叫做直接初始化

还有一点有意思的,C++竟然可以直接使用int()来生成一个临时未命名的int变量,并初始化为0。


这是对内置类型的初始化,对对象的初始化就更有意思了

首先,可以使用普通的构造函数,这一点和java没有区别。

但是C++引入了一种拷贝构造函数,使用这种函数,我们可以实现像内置类型一样形式的初始化。

例如 

myclass A;

myclass B = A;


首先A是一个由默认构造函数生成的对象,而B是用拷贝构造函数生成的对象。

如果是学过Java的人看到这里,一定觉得这是B持有了A的引用,并不是生成了一个新的对象。其实不是,这是C++的一个语法特征,我们可以定义一个构造函数,它的参数只能是一个本类的引用,经常会直接把这个参数设成const,毕竟我们是对它进行拷贝,而不是修改它,关键的一点也是如果A是一个const对象,如果参数不是const的引用,这里就会报错。继续刚才,这个构造函数实现的功能就是复制一遍A。


这里有两个问题

1.我们没有使用这个构造函数啊,我们使用的是等号啊。

这就是C++的语法特征,如果我们没有使用等号,而是用括号传入A,这就和普通的构造函数没有区别了,这叫做直接初始化。C++遇见用等号初始化一个对象时就自动查找是否有这么一个拷贝构造函数。事实上这个构造函数基本上有

2.我们没有定义这个构造函数啊,怎么会使用了它?

C++自动帮用户实现了一个合成拷贝构造函数,这个函数的功能就是拷贝传入的A的全部成员变量,对于内置类型,使用拷贝初始化,对于对象,使用对象的拷贝构造函数。


现在就清楚了为什么我们可以有这样的举动了,那么像C++string类的拷贝构造函数为什么可以接受一个C语言风格的字符串?这里就是C++另外一个语法特性 叫做类的隐式转换。

当一个函数需要某个对象时,我们可以传入一个不是这种类型的对象,前提是这个类有一个构造函数的参数是这种类型。C++就会自动的通过这个对象和符合这个对象的构造函数生成一个临时的变量,通过这个临时变量传给函数。

像 string a = "helloworld"; 虽然“helloworld”不是string类型,但string有一个参数为const char*的构造函数,就使得这里的字面值自动转化为string类型,然后调用了a的拷贝构造函数。


拷贝构造函数的使用场合不仅仅在用等号初始化一个对象时,当一个函数的参数是一个非引用对象时,会自动对实参进行拷贝;当一个函数的返回值是一个非引用对象也会这样。

评论

热度(8)