拷贝构造函数和无参构造函数,深浅拷贝

1.何为构造函数 
 

       1.1构造函数是什么?这个,怎么说都可以,其主要作用是初始化,也可以说了是c++提供的一种初始化的格式方法吧,我没觉得他有多么神奇,牛逼。

具体来说就是 没有返回值,(是没有,不是void),函数名和类名相同,在创建对象,分配内存的时候,就进行了初始化,可以重载 这不就是我c结构体在创建的时候大括号初始化嘛,【构造函数其实主要是用于编译器调用】我觉的这句话是非常不严谨的,也是在扯淡,很多人的博客这样写。如果你稍微区分一下,编译器这么会有调用功能,你的程序里面的代码什么时候调用执行,是看你编译完,什么时候打开运行,然后分配对象空间,然后调用构造函数,进行成员的初始化。
这句话应该是构造函数的调用代码,编译器会帮你生成。没有写构造函数,编译器也会帮你生成代码,而不是调用。

1.2构造函数 的初始化方法很多

# include<iostream>
# include <string>
using namespace std;

class Test
{

public :
	int a;
	int b;
	int c;
	Test(int a)
	{
	  this->a=a;
	}
};

int main (void)
{

    Test  oo(4); //方法1
    Test  o1=Test(4); //方法2
    Test  o2 =4; // 方法3

return 0;
}

2.c++中默认提供了俩个特殊的构造函数,那就是无参构造函数和拷贝构造函数。

其特殊,在于自动生成,当然是在你没有写的时候就会生成,无参构造函数很普通,就是没有参数的构造函数,而拷贝构造函数,主要是该构造函数的参数是当前类的引用,那就意味着什么?意味着我们在构造函数传参的时候,参入一个类的引用,然后把当前的参数初始化为,传入引用的里面的值。听着好难。其实简单来说就是一个拷贝的过程,如,我们需要一个类的俩个对象,把对象1 的初始化内容,赋值给对象2。过程是什么样子的?


当然上图画的墨迹了,其实很简单嘛,搞什么对象,类,等等等等(当然我不是说不好,是在我们需要看透的时候,容易蒙蔽),不就是定义了俩块空间,其中一块空间已经初始化,然后拿着其中一块空间的首地址,通过偏移寻址的方式拿到已经初始化了的成员的值,赋值于未初始化空间的各个相对应的成员。当然你可能说,你这是c的思想,人家是有专有名词的,其实很多东西,看不透的原因往往是你被他那种高大上的外表蒙蔽了,我之所以敢这么说,不管他多牛逼,最终还是要生成汇编代码,不服我们反汇编看看,其实底层的实现就如我上面所述。

# include<iostream>
# include <string>
using namespace std;

class Test
{

public :
	int a;
	int b;

	Test(int a,int b)
	{
	  this->a=a;
	  this->b=b;
	}

	Test(const Test &test )
	{
	  a=test.a;
	  b=test.b;
	}
};

int main (void)
{

	Test  oo(4,5);
    Test &ll=oo;
    Test  xx= ll;
	cout<< "对象oo的值  "<<oo.a<<" "<<oo.b<<endl;
    cout<< "对象xx的值  "<<xx.a<<" "<<xx.b<<endl;

return 0;
}
结果:
对象oo的值  4 5
对象xx的值  4 5
Press any key to continue

3,好了上面我们说了,他这种拷贝构造函数的特点,就是单纯的拷贝,我们把他叫做浅拷贝,当然现在说他是肤浅拷贝你可能不同意,人家都拷贝了,还有什么肤浅不肤浅。下面我们看下面的代码

# include<iostream>
# include <string>
using namespace std;


class Test
{


public :
	int *a;
	int b;


	Test(int a,int b)
	{
	  this->a=new(int);
	  this->b=b;
	}


	Test(const Test &test )
	{
	  a=test.a;
	  b=test.b;
	}
};


int main (void)
{
   
      Test  oo(4,5);
    Test &ll=oo;
    Test  xx= ll;
	cout<< "对象oo的值  "<<oo.a<<" "<<oo.b<<endl;
    cout<< "对象xx的值  "<<xx.a<<" "<<xx.b<<endl;


return 0;
}


输出结果:
对象oo的值  00852FB8 5
对象xx的值  00852FB8 5
Press any key to continue

结果似乎没什么不对,但是问题劝来了,那就是对象xx里面的成员指针,该不该执行和oo一样,如果从代码上来说
毫无问题,结果也是如此,但是实际中,这样就可能出事,因为我们的拷贝构造函数太傻,只是知道拷贝,不知道自己也给自己的a分配一块属于自己的4字节空间,而是把自己的a指向了人家oo的分配空间了,当然,凡事没有绝对,你要有意为之没有错,就怕是你原本是想各自有各自的空间,结果。。。。这就说,为什么是肤浅拷贝,因为他不会分辨。
解决方案很简单。我们自己改下构造函数
# include<iostream>
# include <string>
using namespace std;


class Test
{


public :
	int *a;
	int b;


	Test(int a,int b)
	{
	  this->a=new(int);
	  this->b=b;
	}


	Test(const Test &test )
	{
	  a=new(int);
	  b=test.b;
	}
};


int main (void)
{
   
	Test  oo(4,5);
    Test &ll=oo;
    Test  xx= ll;
	cout<< "对象oo的值  "<<oo.a<<" "<<oo.b<<endl;
    cout<< "对象xx的值  "<<xx.a<<" "<<xx.b<<endl;


return 0;
}


结果

对象oo的值  00592FB8 5
对象xx的值  00592E50 5
Press any key to continue

好了这样就是深拷贝了

2017年8月28日00:14:16 终于可以睡了

猜你喜欢

转载自blog.csdn.net/u013372900/article/details/77624223