C++拷贝赋值操作

拷贝赋值

  • 介绍
  • 源码
  • 运行结果
  • 笔记扩充(下列内容了解即可)
    • 成员指针 介绍
    • 成员指针 源码
    • 成员指针 运行结果

介绍

  • 拷贝赋值注意事项
    1.拷贝赋值也有深拷贝和浅拷贝
    2.如果类中没有定义赋值运算符重载函数,编译器会提供一个 默认的赋值运算符函数
    3.拷贝赋值应尽可能 复用拷贝构造 和 析构函数 代码
    4.尽量避免使用 指针型成员变量、缺省拷贝构造函数、缺省拷贝赋值运算符函数 因为都只是浅拷贝
    5.尽量通过 引用 或 指针 向函数传递 对象型参数,减少拷贝构造,提高效率
    6.若提供了自定义 拷贝构造函数 ,那么也要提供 拷贝赋值运算符函数
  • 与拷贝构造相比,拷贝赋值需要做的操作有:
    1.避免自赋值
    2.分配新资源
    3.拷贝新内容
    4.释放旧资源
    5.返回自引用

源码

#include
#include
using namespace std;
class Array
{
	friend ostream& operator<<(ostream& out,Array& arr);
	friend istream& operator>>(istream& out, Array& arr);
public:
	//下标访问
	char& at(int index)
	{
		return m_array[index];
	}
	//获取空间大小
	size_t size()
	{
		return m_size;
	}
public:
	// = 运算符重载
	Array& operator=(const Array&that)
	{
		cout << "拷贝赋值函数" << endl;
#if 0
		//基本方法拷贝赋值
		if (&that != this)//判断是否重复拷贝赋值自己
		{
			//防止new失败 先用临时变量来存储
			char*ptemp = new char[that.m_size];
			if (ptemp == nullptr)//new失败后的处理方式
			{
				cerr << "Bad Allocation" << endl;
				return *this;
			}
			strcpy(ptemp, that.m_array);//拷贝字符串
			if (m_array)//判断是否为空,释放旧资源
			{
				delete[] m_array;
				m_array = NULL;
			}
			swap(ptemp, m_array);//如果new成功则交换数据
			delete[]ptemp;//以防万一手动释放一遍
			m_size = that.m_size;//获取空间大小
		}
		return *this;
#endif
#if 1 
		//大佬方法拷贝赋值
		if (&that != this)//判断是否重复拷贝赋值自己
		{
			Array temp(that);//利用拷贝构造操作分配新资源
			swap(m_array, temp.m_array);//交换新旧资源 
		}//当判断结束自动释放临时变量
		
		return *this;//返回操作对象
#endif
	}
public:
	//初始化构造
	Array(size_t size = 0)
	{
		cout << "构造函数" << endl;
		m_array = new char[size];//动态数组创建
		m_size = size;//记录动态数组大小
	}
	//拷贝构造
	Array(const Array&that)
	{
		cout << "拷贝构造函数" << endl;
		m_array = new char[that.m_size];//创建一个同样大小的空间
		strcpy(m_array, that.m_array);//拷贝字符串
		m_size = that.m_size;//获取空间大小
	}
	//析构函数
	~Array()
	{
		cout << "析构函数" << endl;
		//销毁动态数组
		if (m_array)
		{
			delete[] m_array;
			m_array = NULL;
		}
	}
private:
	char* m_array;//字符串数组
	size_t m_size;//size_t是unsigned int(无符号整形)
};
//提取(<<)重载
ostream& operator<<(ostream& out, Array& arr)
{
	for (int i = 0; i < arr.m_size; i++)
	{
		//输出
		out << arr.m_array[i] << "\t";
	}
	out << endl;
	return out;
}
//输入(>>)重载
istream& operator>>(istream& in, Array& arr)
{
	for (int i = 0; i < arr.m_size; i++)
	{
		//输入
		in >> arr.m_array[i];
	}
	return in;
}
void main()
{
	//单字符串输入输出
	Array *p_array = new Array(4);
	//输入
	cin >> *p_array;
	//输出
	cout << *p_array;
	cout << "--------------分隔符--------------" << endl;
//拷贝构造
	Array *p_array2 = new Array(*p_array);//默认拷贝构造
	{
		Array p_array4 = *p_array;//默认拷贝构造(自动析构)
		cout << p_array4;
	}
	cout << "--------------分隔符--------------" << endl;
	{
		//默认浅拷贝(默认赋值函数)
		Array *p_array3 = p_array;
		//默认浅拷贝(默认赋值函数)
		Array *p_array5;
		p_array5 = p_array;
	}
//拷贝赋值
	Array *p_array6 = new Array;//先构造
	*p_array6 = *p_array;//拷贝赋值
	cout << "--------------分隔符--------------" << endl;
//析构
	delete p_array;
	delete p_array2;
	delete p_array6;
	system("pause");
}

运行结果

构造函数
1253
1       2       5       3
--------------分隔符--------------
拷贝构造函数
拷贝构造函数
1       2       5       3
析构函数
--------------分隔符--------------
构造函数
拷贝赋值函数
拷贝构造函数
析构函数
--------------分隔符--------------
析构函数
析构函数
析构函数
请按任意键继续. . .

笔记扩充(下列内容了解即可)

成员指针 介绍

成员指针(用来存储 相对地址(偏移值)) 指向 成员变量的指针

成员指针 源码

#include
#include
using namespace std;
class Integer
{
public:
	Integer(int i = 0) :m_i(i){}
	int m_i;
	int m_a;
	int m_c;
};
void main()
{
	Integer i1(10), i2(20);
	int *p1 = &i1.m_i;
	int *p2 = &i2.m_i;

	//成员指针(用来存储 相对地址(偏移值)) 指向 成员变量的指针
	//int Integer::*p指向类中int类型变量的指针
	int Integer::*p = &Integer::m_i;
	i1.*p = 50; 
	cout << i1.m_i << endl;
	cout << "--------------分隔符--------------" << endl;
	//偏移测试
	int Integer::*pp = NULL;
	cout << *(int*)&pp << endl;//强转类型打印值,获取偏移值
	pp = &Integer::m_i;
	cout << *(int*)&pp << endl;//强转类型打印值,获取偏移值
	pp = &Integer::m_a;
	cout << *(int*)&pp << endl;//强转类型打印值,获取偏移值
	pp = &Integer::m_c;
	cout << *(int*)&pp << endl;//强转类型打印值,获取偏移值
	system("pause");
}

成员指针 运行结果

50
--------------分隔符--------------
-1
0
4
8
请按任意键继续. . .

你可能感兴趣的:(C++学习参考,c++,学习,笔记)