拷贝构造函数之深拷贝浅拷贝

来源:互联网 发布:单片机相序检测程序 编辑:程序博客网 时间:2024/05/29 08:30

何为拷贝构造函数?

一般一个构造函数的参数是自身类类型的const引用,则这个构造函数就是拷贝构造函数。

拷贝构造函数是被用来初始化 非引用类 类型参数, 参数必须是引用类型。

如:

class MyString

{

  public:

       MyString( const MyString&  Mystr);                             //拷贝构造函数

};

如果我们没有自己定义拷贝构造函数,编译器就会自动会定义一个合成拷贝构造函数。

/********************************************************************************************************/

说到拷贝构造函数,得扯扯构造函数。

1、构造函数的作用就一点: 初始化!!!分配内存不是构造函数管得到的事情。

malloc/free就仅仅是分配内存;

而new/delete分配内存,如果存在构造函数就会调用构造函数。如:内置类型,int double 等并没有构造函数new操作就没有初始化这一步,而像string 类类型等就会调用构造函数初始化。

2、编译器在需要构造函数时才会合成构造函数;初始化时,如果有对应的构造函数,编译器就会帮你调用之。编译器只会帮你到这。。。

/********************************************************************************************************/

回到正题:

如果我们没有自定义copy constructor,编译器就会合成拷贝构造函数,然而这个copy constructor是位拷贝实现的,这是很危险的,我做了一些实验做以验证。

先来说说深拷贝浅拷贝:

浅拷贝就是位拷贝,意思是按地址进行拷贝,深拷贝就是值拷贝,拷贝的是内容。可这样理解:如果一个类拥有资源(堆等),当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。

浅拷贝时,两个类对象同时指向同一块内存地址,当一个对象被delete时,对应的内存位置会被释放,这时另一个对象的内存指针就变成了野指针,这很危险。这时就应该编写operator=和copy constructor来实现值拷贝。

代码如下:

/*拷贝构造函数*/
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<cstring>
using namespace std;


class MyString
{
friend class ShowMyString;//友元类
public:
MyString(string s, int l, char* p) //有参构造
{
S = s;
length = l;
if (p == NULL)
{
P = new char[1];
p[0] = '\0';
}
else
{
P = new char[length + 1];
strcpy(P, p);
}

}
MyString(const MyString& mys)//拷贝构造函数 深拷贝
{
S = mys.S;
length = mys.length;
//P = new char[length + 1];//深拷贝(拷贝一个非引用类类型,重新分配资源)若是深拷贝 指针pstr安全,输出hhhh.
//if (P != 0)
//{
// strcpy(P, mys.P);
// P[length] = '\0';
//}
P = mys.P;//直接指针赋值导致浅拷贝
}
~MyString()
{
if (P != NULL)
{
delete[] P;
}
}
void showstr()
{
cout << "C++风格的字符串:" << S << endl << "C风格的字符串:" <<P << endl;
}
private:
string S;
char* P;
int length;
};


class ShowMyString
{
public:
void show(MyString& ms);

};


void ShowMyString::show(MyString& ms)
{
cout <<"C++风格的字符串:" << ms.S <<endl<< "C风格的字符串:" << ms.P << endl;
}
int  main()
{
MyString * pstr = NULL;
{
MyString s("hello", 4, "hhhh");
ShowMyString sh;
sh.show(s);
pstr = new MyString(s);
}  //对象s被delete,此时指针pstr为野指针,输出乱码了
pstr->showstr();
cout << endl;
////////////////////////////////
/*MyString s1 = s;
sh.show(s1);*/
system("pause");
return 0;
}

浅拷贝的结果:


深拷贝的结果:


0 0