C++_拷贝构造介绍

介绍

PS:浅拷贝不适用于 动态数组赋值

拷贝构造中如果有 new 一个对象,建议采用深拷贝形式进行赋值; 详细参考文章:c++拷贝赋值 and C++拷贝赋值操作

无参构造

1.如果创建一个 类 没有写任何构造函数,则编译器会自动生成一个无参构造函数,定义内容为空
2.只要定义了 某一种构造函数,则系统不在自动生成 默认的构造函数
3.如果需要一个默认构造函数,则需要自己显示地写出来

参考源码

//默认无参构造函数
class A
{
	A(){}
};

数据类型转换

数据类型转换构造 不需要 单参对应(PS: 单参 double 可以可以转换 int 类型变量)
例如:
1.声明样式:Complex(double real)
2.调用样式:Complex cp1 = 1.2;//隐式调用单参或者Complex cp1(1.2);//显示调用单参
参考代码段

//类型转换构造
	Complex cp1 = 1.2;//会隐式调用类型转换构造
	cp1.print();

拷贝构造

例如:
1.声明样式:Complex(Complex& that);
2.调用样式:Complex cp2 = cp1;//隐式调用拷贝构造或者Complex cp2(cp1);//显示调用拷贝构造

  • (1).拷贝构造 注意事项
    1.编译器会默认给一个空内容的 拷贝构造
    (PS:如果提供了拷贝构造函数,则不在提供默认拷贝构造函数)
    2.从相同类型的对象来构造对象(参数中 类型 要与 类名 相同)
    3.拷贝构造 中有 数据溢出风险
    4.拷贝构造 需要有 显示构造函数
  • (2).拷贝构造 作用(PS:拷贝后值一样,地址不一样)
    1.用于根据一个已存在的对象复制出一个新的同类 类型对象

参考代码段

//拷贝构造
	Complex cp2 = cp1;//会隐式调用拷贝构造
	cp2.print();

浅拷贝

  • (1).浅拷贝 注意事项
    (PS:可以把浅拷贝当做一种BUG存在一样,无需主动释放)
    1.当delete age 后 age2也会被delete掉,因为 age2 相当于继承了age

中断结果图:
在这里插入图片描述

  • (2).浅拷贝 作用(PS:拷贝后值一样,地址一样)
    1.对内存地址的复制,让目标指针和源指针指向同块内存
    2.通过其中一个指针去释放内存,其他指向改内存的指针会成为 野指针

错误代码段参考

	Complex *age = new Complex(20);//显式调用单参构造重载
	age->introduce();
	Complex *age2 = new Complex(*age);//浅拷贝
	age2->introduce();

	delete age2;//当delete age后 age2也会被delete掉

深拷贝

  • (1).深拷贝 作用(PS:拷贝 内存)
    1.深拷贝会将整个内存都进行拷贝获取
  • (2).深拷贝 注意事项
    1.需要开足够的空间进行拷贝获取
    2.当有 double类型转换构造函数 还有 int类型转换构造函数 会形成 调用不明确
    (PS:有可能会调用 int类型转换构造函数 也有可能 double类型转换构造函数 )

参考代码段

	Complex *age = new Complex(20);//显式调用单参构造重载
	age->introduce();

	Complex *age2 = new Complex(*age);//浅拷贝
	age2->introduce();

	delete age;
	age2->introduce();

源码

main.cpp

#include<iostream>
#include<string>
#include"Complex.h"
using namespace std;

void main()
{
//构造函数
#if 0
	Complex*p_ca = new Complex;
	p_ca->print();
	delete p_ca;
#endif
//类型转换构造
#if 0
	Complex cp1 = 1.2;//会隐式调用类型转换构造
	cp1.print();
#endif
//拷贝构造(拷贝值和地址)
#if 0

	Complex cp2 = cp1;//会隐式调用拷贝构造
	cp2.print();
#endif
//浅拷贝(只拷贝地址)(PS:这段代码会报错)
#if 0
	Complex *age = new Complex(20);//显式调用单参构造重载
	age->introduce();
	Complex *age2 = new Complex(*age);//浅拷贝
	age2->introduce();

	delete age2;//当delete age后 age2也会被delete掉
#endif
//深拷贝构造(拷贝内存)(PS:不能与类型转换构造同时使用,会造成调用错误)
#if 1
	Complex *age = new Complex(20);//显式调用单参构造重载
	age->introduce();

	Complex *age2 = new Complex(*age);//浅拷贝
	age2->introduce();

	delete age;
	age2->introduce();
#endif
	system("pause");
}

Complex.h

#pragma once

class Complex
{
public:
	//无参构造
	Complex();
	//单参构造,参数不是同类类型 叫类型转换构造函数
	Complex(double real);
	//单参构造,参数是同类类型 叫拷贝构造函数
	Complex(const Complex& that);
	//单参构造重载
	explicit Complex(int age);//explicit防止隐式调用
	//析构
	~Complex();
public:
	//声明函数print()
	void print();
	//声明函数introduce()
	void introduce();
private:
	double M_real;//实部
	double M_vir; //虚部
	int *M_pAge;  //年龄
};

Complex.cpp

#include "Complex.h"
#include<iostream>
#include<string>
/**************************************************
此文件是Complex.h中的声明后需要定义的文件
1.用来写程序实现步骤
2.方便查看程序
(PS:如果只在Complex.h中声明 无定义则报错无法解析)
**************************************************/
using namespace std;

//无参构造
Complex::Complex()
{
	M_real = 0;
	M_pAge = NULL;
	M_vir = 0;
	cout << "无参构造" << endl;
}

//单参构造,参数不是同类类型 叫类型转换构造函数
Complex::Complex(double real)
{
	M_real = real;
	M_vir = 0;
	cout << "类型转换构造" << endl;
}

//单参构造,参数是同类 类型 叫拷贝构造函数
Complex::Complex(const Complex& that)
{
	M_real = that.M_real; 
	M_vir = that.M_vir;
浅拷贝
//	M_pAge = that.M_pAge;//只复制地址
//深拷贝
	M_pAge = new int(*(that.M_pAge));//开空间后赋值
	cout << "拷贝构造" << endl;

}

//单参构造重载
Complex::Complex(int age)
{
	cout << "单参构造重载" << endl;
	if (age > 0)//判断所传入的值是否大于0
	{
		M_pAge = new int(age);//赋值
	}
}

//打印复数
void Complex::print()
{
	cout << M_real << "+" << M_vir << "i" << endl;
}
//打印年龄
void Complex::introduce()
{
	cout << "My " << *M_pAge << " old years" << endl;
}

Complex::~Complex()
{
	if (M_pAge !=NULL)
	{
		delete M_pAge;
		M_pAge = NULL;
	}
	cout << "析构成功" << endl;
}
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值