Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / 浅析:浅拷贝 及 深拷贝的传统写法

浅拷贝会造成指针悬挂的问题。 举个例子:两个对象是s1和s2的指针_str都指向new开辟的同一块空间,如下图,主程序结束时,对象逐个撤销,先撤销对象s2,会调用析构函数释放动态分配的内存;再撤销对象s1时,s1._str所指向的内存空间已经是无法访问了,而s2._str原先指向的那块内存却无法释放,出现了所谓的指针悬挂! 两个对象企图释放同一块内存,从而导致一块内存被释放两次这也是不行的,运行会出错。#include <iostream>
using namespace std;class String
{
public:
         String(char *str)
                    :_str(new char [strlen(str )+1])
         {
                              strcpy(_str, str);
         }
         String(const String & s)
         {
                    _str = s._str;
         }
         String& operator=(const String & s )
         {
                    if (this !=&s)
                    {
                              _str = s._str;
                    }
                    return *this ;
         }
         ~String()
         {
                    delete[] _str;
         }
private:
         char* _str;
};void Test()
{
         String s1("Lynn" );
         String s2=s1;
}
int main()
{
         Test();
         system("pause" );
         return 0;
}深拷贝  深拷贝解决了指针悬挂的问题,当调用拷贝构造或赋值运算符的重载函数时,程序会生成一份该内存的拷贝,这样每个指针都会指向一块相对独立的空间,撤销对象时调用析构函数,分别释放他们自己的动态分配的内存,相互之间不影响。如下图:深拷贝
///////////////////////////////////////////////////////////////////////////////////////
 
//          写String类的构造函数时一定要注意参数问题
//          首先要考虑到构造的对象分有参数和无参数两种情况
//          构造对象的时候不能直接赋值,否则一块内存两次释放的话程序会出错
//          无参的构造函数不能将_str指针赋值为NULL,因为不能strlen(NULL)
//          赋值运算符的重载要考虑到有可能分配内存失败的问题
//          当然,记得要给""分配空间哦
//                                                                   By:Lynn-Zhang
//////////////////////////*****************////////////////////////////////////////////
 
#include<iostream>
using namespace std;
 
class String
{
public:
           
         String(char * str="")          //不能strlen(NULL)
                    :_str(new char [strlen(str ) + 1])
         {
                    strcpy(_str, str);
         }
         String(const String &s)
                    :_str(new char [strlen(s ._str) + 1])
         {
                    strcpy(_str, s._str);
         }
           
         //赋值运算符的重载
         String& operator=(const String& s)
         {
                    if (this != &s )
                    {
                        /*   //有可能开辟空间失败,但是却破坏了_str的内容
                             delete[] _str;
                             _str = new char[strlen(s._str) + 1];
                             strcpy(_str, s._str); */
 
                              char* tmp = new char [strlen(s ._str) + 1];
                              strcpy(tmp, s._str);
                              delete[] _str;
                              swap(_str, tmp);
 
                    }
                    return *this ;
         }
         char* CStr()
         {
                    return _str;
         }
         ~String()
         {
                    delete[] _str;
         }
private:
         char* _str;
};
 
 
//函数测试
void Test()
{
         String s1("aaaaa" );
         cout << s1.CStr() << endl;
         String s2(s1);
         cout << s2.CStr() << endl;
         String s3 = s1;
         s3= s2;
         cout << s3.CStr() << endl;
         String s4;
         // s4 = s1;
         cout << s4.CStr() << endl;
         
}
int main()
{
         Test();
         system("pause" );
         return 0;
}本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/130277.htm