复制构造函数 与 赋值函数 的区别

编程入门 行业动态 更新时间:2024-10-27 16:24:53

复制构造函数 与 赋值函数 的区别

构造函数、析构函数、赋值函数是每个类最基本的的函数。每个类只有一个析构函数和一个赋值函数。但是有很多构造函数(一个为复制构造函数,其他为普通构造函数。对于一个类A,如果不编写上述四个函数,c++编译器将自动为A产生四个默认的函数,即:

A(void)                                    //默认无参数构造函数A(const A &a)                         //默认复制构造函数~A(void);                                //默认的析构函数A & operator = (const A &a); //默认的赋值函数

既然能自动生成函数,为什么还需要自定义?原因之一是“默认的复制构造函数”和"默认的赋值函数“均采用”位拷贝“而非”值拷贝“

位拷贝  v.s.  值拷贝

为便于说明,以自定义String类为例,先定义类,而不去实现。

#include <iostream>
using namespace std;class String  
{public:String(void);String(const String &other);~String(void);String & operator =(const String &other);private:char *m_data;int val;
};

位拷贝拷贝的是地址,而值拷贝拷贝的是内容。

如果定义两个String对象a, b。当利用位拷贝时,a=b,其中的a.val=b.val;但是a.m_data=b.m_data就错了:a.m_data和b.m_data指向同一个区域。这样出现问题:

a.m_data原来的内存区域未释放,造成内存泄露a.m_data和b.m_data指向同一块区域,任何一方改变,会影响到另一方当对象释放时,b.m_data会释放掉两次

因此

当类中还有指针变量时,复制构造函数和赋值函数就隐含了错误。此时需要自己定义。

结论

有一种特别常见的情况需要自己定义复制控制函数:类具有指针哈函数。赋值操作符和复制构造函数可以看成一个单元,当需要其中一个时,我们几乎也肯定需要另一个三法则:如果类需要析构函数,则它也需要赋值操作符和复制构造函数

注意

如果没定义复制构造函数(别的不管),编译器会自动生成默认复制构造函数如果定义了其他构造函数(包括复制构造函数),编译器绝不会生成默认构造函数即使自己写了析构函数,编译器也会自动生成默认析构函数

因此此时如果写String s是错误的,因为定义了其他构造函数,就不会自动生成无参默认构造函数。

复制构造函数  v.s.  赋值函数

#include <iostream>
#include <cstring>
using namespace std;class String  
{public:String(const char *str);String(const String &other);String & operator=(const String &other);~String(void); private:char *m_data;
};String::String(const char *str)
{cout << "自定义构造函数" << endl;if (str == NULL){m_data = new char[1];*m_data = '\0';}else{int length = strlen(str);m_data = new char[length + 1];strcpy(m_data, str);}
}String::String(const String &other)
{cout << "自定义拷贝构造函数" << endl;int length = strlen(other.m_data);m_data = new char[length + 1];strcpy(m_data, other.m_data);
}String & String::operator=(const String &other)
{cout << "自定义赋值函数" << endl; if (this == &other){return *this;}else{delete [] m_data;int length = strlen(other.m_data);m_data = new char[length + 1];strcpy(m_data, other.m_data);return *this;}
}String::~String(void)
{cout << "自定义析构函数" << endl; delete [] m_data;
}
int main()
{cout << "a(\"abc\")" << endl;String a("abc");cout << "b(\"cde\")" << endl;String b("cde");cout << " d = a" << endl;String d = a;cout << "c(b)" << endl;String c(b);cout << "c = a" << endl;c = a;cout << endl;
}

执行结果

说明几点

1. 赋值函数中,上来比较 this == &other 是很必要的,因为防止自复制,这是很危险的,因为下面有delete []m_data,如果提前把m_data给释放了,指针已成野指针,再赋值就错了

2. 赋值函数中,接着要释放掉m_data,否则就没机会了(下边又有新指向了)

3. 拷贝构造函数是对象被创建时调用,赋值函数只能被已经存在了的对象调用

    注意:String a("hello"); String b("world");  调用自定义构造函数

             String c=a;调用拷贝构造函数,因为c一开始不存在,最好写成String c(a);

更多推荐

函数,赋值,区别

本文发布于:2023-05-29 15:07:07,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/347266.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   赋值   区别

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!