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