拷贝构造函数和赋值运算符重载

拷贝构造函数 :

1概念

拷贝构造函数只有单个形参,该形参是对本类类型对象的引用(常用const 修饰),
使用已存在的类类型的对象创建新对象时,编译器自动调用该函数。
eg:
假如 Claa A{
public:A(const A& a){}
private :
int a;},
A a ,
A b(a);
2 特征

1 只有一个参数: 引用传参,传值方式将会无限递归(Why)
传值无限递归原因:传值时拷贝构造函数的形参将会拷贝传来的值,也是一个拷贝构造同时也是一个拷贝相当于A b(a);因为类并没有正确实现引用,所以将在形参接收这里无限递归下去。

另外,写成传值编译器将会报错

2 拷贝构造函数是构造函数的一个重载形式,(言下之意,构造函数还有别的函数重载形式)

3 若未进行显式地定义拷贝构造函数,编译器将隐式地生成一个拷贝构造函数,。今天我来补充一下,另一个构造的重载:C++11 提出的引用构造(右值引用) eg: string(string&& s )

4 .既然编译器能自己生成默认的拷贝构造函数,那我们还要自己定义吗?
答案是 肯定的
理由:编译器并不知道我们的类中是怎样的成员,有没有多次使用用一个类对象定义拷贝构造函数,假如说我们在类中 并没有申请(管理)内存空间,那么出类时,析构函数将会正常的销毁类中的成员(空间资源),释放内存。 但是, 请你想一想,假如你的类中 申请了空间(管理了内存空间),而你申请的空间被拷贝构造函数使用 (换句话说,就是假如拷贝构造函数使用了你申请的内存空间,并拷贝出了多个类 类型的对象),这会发生什么?? 这会导致你申请的空间被同时多个类类型对象共用(换句话说,多个类类型对象指向同一空间(同一对象)),而析构函数会销毁你的所有成员,导致同一申请的空间释放多次这当然不行了!!!
所以,我们显式地写个拷贝构造函数是很有必要的!(目前我能力还不行,但是道理我懂了,加油)

以下代码为什么会崩掉?留待以后回来看看

   #include"iostream"
#include"string.h"
#include"stdio.h"
#include "windows.h"
using namespace std;
class String
{
public :
		// 拷贝构造函数
		String(const char* str = "Jack")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	//析构函数
	~String()
	{
		cout <<"~String()"<< endl;
		//printf("%s","~String()");
		free(_str);
	}
private:
	char * _str;
};
int main(void)
{
	String s1("hello");//调用编译器默认生成的构造函数
	String s2(s1);
	system("pause");
	return 0;
}

2 赋值运算符重载

概念:什么是赋值运算符重载?
赋值运算符重载就是:编译器本来不支持该类型的运算,但是用户想实现,所所以产生这个函数。
运算符重载是不是听着就很不一样??
它也是一种函数重载。

函数格式 : 返回值类型 + operate +运算符(参数列表){函数体}
特征: operate 关键字后边 + 运算符符号
注意: 1 不能自己创建新的运算符,运算符就是运算符,不是个别人定义的
2 参数列表必须至少有一个 枚举类型或者类类型的对象
3 运算符的语义不允许更改 eg: 外部为 operate+(参数列表){return a-b;}
这样是错误的!
4 若为类的成员的 (重载)函数,参数还有一个隐藏的this指针,即参数数量+1

5 <1> . * <2 > :: <3>s izeof <4>? : <5> . 这5个运算符不能做重载函数 。笔试题常常出现

你可能感兴趣的:(6个默认成员函数,赋值运算符重载,拷贝构造函数,为什么拷贝构造传引用)