含有指针变量的类需要重写拷贝构造函数,拷贝赋值函数,析构函数

编译器自带拷贝构造(ctor)和拷贝赋值函数(operator =), 但是对于成员变量含有指针的类,其不能使用默认的拷贝赋值函数。因为使用默认的,会直接将指针指向的地址进行赋值 (浅拷贝,共享内存,共指一个对象),而不是分配一块内存,具有相同的数值 (深拷贝,独立,两个对象)。

浅拷贝容易造成dangling pointer。

用一个例子来展示:

 1 #ifndef __MYSTRING__
 2 #define __MYSTRING__
 3
 4 class String{
 5     public:
 6         String(const char* cstr=0);
 7         String(const String& str);  // 拷贝构造
 8         String& operator= (const String& str);  // 拷贝赋值
 9         ~String();
10         char* get_c_str const(){
11             return m_data;
12         }
13     private:
14         char* m_data;  // 带指针成员的类:一定要注意拷贝赋值,拷贝构造,析构
15         // String的底部通过char实现,在外部表现为string
16 };
17
18 inline String::String ( const char* cstr=0 ){
19     if(cstr){
20         m_data=new char[strlen(cstr)+1];
21         strcpy(m_data,cstr);  //  char * strcpy ( char * destination, const char * source );
22     }
23     else{ // 考虑cstr=0;
24         m_data=new char[1];
25         m_data[0]=‘\0‘;
26     }
27 }
28
29 inline String::String(const String& str){
30     m_data=new char[strlen(str.get_c_str())+1];
31     strcpy(m_data,str.m_data);
32 }
33
34 inline String::~String(){
35     delete[] m_data;
36 }
37
38 inline String& String::operator=(const String& str){
39     if(this==&str){ // self assignment :自我检验  (如果没有进行这样的处理,在自我赋值会产生严重的错误)
40         return *this;
41     }
42     // 构造函数是第一次,因此不需要删除,但是赋值需要先进行delete
43     delete[] m_data;  // 先删除,重新分配一样大小!
44     m_data=new char[strlen(str.get_c_str())+1];
45     strcpy(m_data,str.m_data);
46     return *this;   // 其实不用返回*this也可以,因为已经实现了修改,但是这样有一个好处  可以实现 a=b=c;  (因为返回的类型继续支持=)
47 }
48
49 // 调用形式: cout <<  String() ;   第一个参数为 << 左边 ,第二个参数为 << 右侧;返回ostream 可以实现 cout <<  a << b ;
50 ostream& operator<<(ostream& os,const String& str){
51     os<<str.get_c_str();
52     return os;
53 }
54
55 #endif

原文地址:https://www.cnblogs.com/yy-1046741080/p/12271659.html

时间: 2024-08-29 14:00:07

含有指针变量的类需要重写拷贝构造函数,拷贝赋值函数,析构函数的相关文章

CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数 class Person{ public : Person():age(10), name(NULL); Person(int myage, char *myname); Person(const Person &a); ~Person(void); void set_age(int myage); void get_age(void); void set_other_age(Person &a, int b); private: i

拷贝构造函数和赋值函数

在 C++ 中,赋值和拷贝是不同的, 1)拷贝构造函数是对未初始化的内存进行初始化操作 2)而赋值是对现有的已经初始化的对象进行操作.(这里我对"已经初始化"的理解是已经调用了构造函数,并且构造函数体可以未执行,只要调用到即可),赋值函数应该给所有数据成员都初始化. 3)重点:包含动态分配成员的类 应提供拷贝构造函数,并重载"="赋值操作符. 4)可以说,C++中什么时候有临时对象产生,此时刻c++一定要调用拷贝构造函数.(临时对象产生时有一个特例,此时不需要调用拷

不要轻视拷贝构造函数与赋值函数

由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数 有些轻视.请先记住以下的警告,在阅读正文时就会多心: 本章开头讲过,如果不主动编写拷贝构造函数和赋值函数,编译器将以"位拷贝" 的方式自动生成缺省的函数.倘若类中含有指针变量,那么这两个缺省的函数就隐 含了错误.以类 String 的两个对象 a,b 为例,假设 a.m_data 的内容为"hello", b.m_data 的内容为"world". 现将 a 赋给 b,缺省

C++ 拷贝构造函数与赋值函数的区别(很严谨和全面)

这里我们用类String 来介绍这两个函数: 拷贝构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用.当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用拷贝构造函数.为啥形参必须是对该类型的引用呢?试想一下,假如形参是该类的一个实例,由于是传值参数,我们把形参复制到实参会调用拷贝构造函数,如果允许拷贝构造函数传值,就会在拷贝构造函数内调用拷贝构造函数,从而形成无休止的递归调用导致栈溢出. 赋值函数,也是赋值操作符重载,因为赋值必须作为类成员,那

C++中:默认构造函数、析构函数、拷贝构造函数和赋值函数——转

对于一个空类,编译器默认产生4个成员函数:默认构造函数.析构函数.拷贝构造函数和赋值函数.1.构造函数:构造函数是一种特殊的类成员,是当创建一个类的时候,它被调用来对类的数据成员进行初始化和分配内存.构造函数的命名必须和类名完全相同,构造函数可以被重载,可以多个,可以带参数. eg: class A { public: A(){cout<<"无参构造函数";} A(int i){cout<<"带参构造函数";} }; A();//调用默认构造

C++中拷贝构造函数和赋值函数被调用的时机

一.拷贝构造函数被调用的时机: 1. 当用类的一个对象去初始化该类的另一个对象(或引用)时系统自动调用拷贝构造函数实现拷贝赋值. 2. 若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数. 3. 当函数的返回值是类对象时,系统自动调用拷贝构造函数. 二.赋值函数被调用的时机: 当用一个对象赋值给另一个对象时 注意一.二中初始化和赋值的区别 C++中拷贝构造函数和赋值函数被调用的时机,布布扣,bubuko.com

拷贝构造函数和赋值函数的一些知识

/*******************拷贝构造函数和赋值运算符重载有以下两个不同之处***************************/ 1.拷贝构造函数生成新的类对象,而赋值运算符不能. 2.由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新对象相同,而复制操作符需要这个操作,另外赋值运算符中如果原来对象中有内存分配,要先把内存释放掉. 下面是String类的一个实现的部分函数,可以看出二者的区别. 1 class String{ 2 public:

拷贝构造函数与赋值函数的区别

1.从概念上区分:复制构造函数是构造函数,而赋值操作符属于操作符重载范畴,它通常是类的成员函数 2.从原型上来区分:复制构造函数原型ClassType(const ClassType &);无返回值赋值操作符原型ClassType& operator=(const ClassType &);返回值为ClassType的引用,便于连续赋值操作 3.从使用的场合来区分:复制构造函数用于产生对象,它用于以下几个地方:函数参数为类的值类型时.函数返回值为类类型时以及初始化语句,例如(示例了

类string的拷贝构造函数与赋值函数

//参考高质量c++编程 复制构造函数 1 String ::String (const String &other) 2 { 3 4 5 int length=strlen(other.m_date); 6 //other对象的字符长度,其不包括‘\0’ 7 m_data=new char[length+1]; 8 //在堆上开辟一块内存,内存大小包括'\0' 9 strcpy(m_data, other.m_data); 10 11 } 赋值构造函数 1 String &String