本文主要是介绍关于拷贝构造函数的猜想【很久之前写的】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
书上对拷贝构造函数的解释我看过,是在不怎么让人信服(完全是为了考试的教育,据说是外文翻译过来的,那么这个外国作者水平也不咋滴)。
“拷贝”这个词21世纪的人都知道,就是“复制品”的意思,那么什么是对象的拷贝呢?这个比较好理解,那就是给定一个已经赋值的对象,然后如果存在一个没有赋值的同类对象的时候就可以将已知的对象的相应内容复制过来,而不会改变已知的对象。
以上这些大家自己想想也都能想通,但对于三个会引发拷贝构造函数调用的情况却有点莫名奇妙。其实三种情况不是偶然的,是由C++语言的本质所决定的。为什么这么说呢?我先来讨论第一种情况:
1. 当用类的一个对象去初始化该类的另一个对象时。
比如:
class point
{
public:
point(int xx=0,int yy=0):X(xx),Y(yy)
{
}
point(point &p);
int getX(){return X;}
int getY(){return Y;}
int X;//为了验证一些问题本质,设为公有类型
int Y;
};
point::point(point &p)//此函数的作用是把p的作用
{
cout<<"COPY!!!"<<endl;
}//该函数的功能就是将p的内容复制,即得到p的复制品。
int main()
{
point a(1,2);
point b(a);
}
第一个其实很容易理解,就是把a(源对象)的值赋给b(目的对象)就相当于把a复制给了b。再进一步就是我的理解:b想要a的内容,a为了使自己的内容不受b的影响,于是便用一个函数(拷贝构造函数)来过渡。在我上面写的point(point&p)中b是得到了a的复制品(复制过程是用户自定义的),但是如上的情况b在得到a的引用后却没有做任何的操作。所以其实在这个赋值过后,b的内容还是没有改变(大家可以自行调试)。所以一旦添加了拷贝构造函数,那么就相当于要经过这个函数才能得到源对象的内容,那么就只有在函数体内添加点对点,值对值的赋值。才能完成整体的赋值。所以大家如果用point b=a,得到的结果也是一样的,当然不可以是这样
point b;
b=a;
为什么呢?我们要牢记一个东西:那就是以上所有的赋值都是指“赋初值”的意思,也就是说在目的对象刚建立(申明)的时候源对象才能被其拷贝。(至于为什么,这是因为构造函数的本质:是在一个对象刚建立的时候才能被调用的)而这里的b已经不是真空的了,他已经被赋了一次值。所以b=a不能称的上是赋初值了,所以无效。这时b的值就被赋为a的值了。
到这里,我想大家都应该懂了基本的原因:正是因为类中申明了拷贝构造函数,所以该类的对象有从同类对象获取其副本(或者成一定关系的伪副本:不是一对一的一般赋值)的能力(拷贝构造函数的通融)。而得到与源对象一致或者成一定关系的目的对象。所以“拷贝”的真正含义体现在获得副本上,而并非很多同学与老师所认为的“b获得了与a一样的值,这就叫‘拷贝’”。
我在这个例子中用的拷贝构造函数是“空”的(除了一个输出外)。这就告诉程序,就采用我定义的这个“空”拷贝构造函数,而不需要它自己创建一个值对值的拷贝构造函数。
(在用户没有定义拷贝构造函数时:用户会定义这样一个拷贝构造函数:如下
point::point(point &p)
{
X=p.X;
Y=p.Y;
}
也可以写成:
point::point(point &p):X(p.X),Y(p.Y)
{
}
)
知道了这些,我想对2,3种情况的分析就相当简单了。
2.如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。如:
void f(point p)
{
cout<<p.getX()<<endl;
}
这是因为,形参p正是一个临时建立的point类型。当实参向形参进行值传递的时候,便发生了跟1一样的情况。所以这也会调用拷贝函数。读者可以自己证明,当我们把函数改为
void f(point &p)
{
p.X++;
cout<<p.getX()<<endl;
}
这就相当与告诉了源对象“我不要你的拷贝,我要你本身!”这就是引用的强大。如此,读者会发现,如果是引用,那么如果对其进行改动的话,那么在main函数里的源对象也会发生改变。而如果不用引用,那么就算源对象的“拷贝”被改的面目全非,他自己也不会有任何改变。大家初学的时候都学过swap函数,就是这个原理。对于一般的数据类型(int,float等)之所以也这样,我想大家都会怀疑:他们不会也是这样的类吧?答案是:Yes! 他们的本质也是一种类,也定义了拷贝函数。
int a(12);
int b(a);
cout<<b<<endl;
以上的写法想必很多人都没尝试过,其实也完全正确的。
3.如果函数的返回值是类的对象,函数执行完成返回调用者时。如:
point f2()
{
point h(2,3);
return h;
}
同理。读者自己试着推导一遍。(提示:函数的返回值其实也是相应的变量,在内存中跟同类型的变量的处理方式完全一样。return h就是相当于对返回目的变量赋初值!)
而除去以上这点重要因素之后,就是拷贝与目的函数之间的简单赋值了。
这篇关于关于拷贝构造函数的猜想【很久之前写的】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!