侯捷 c++ 面向对象程序设计

【8】三大函数:拷贝构造、拷贝赋值、析构

如果class中有指针,则不能用编译器给的默认拷贝,需要自己写构造函数来拷贝。
class中有指针,多半是要做动态分配,则一定要有析构函数,delete字符串

以下public里面从上往下,分别是构造函数、拷贝构造函数、拷贝赋值、析构函数。最后一个是一个成员函数,传回指针,不改变data,所以要加上const。
在这里插入图片描述

字符串有多长,有两种设计思路,一种是在字符串最后有个结束符号,另一种是在字符串定义初规定字符串的长度。
有构造函数,就要有对应的析构函数,释放内存。析构函数会被自动调用
class里有指针,多半是要做动态分配的。
在这里插入图片描述

如果有指针的成员函数,但是没有对应的构造函数和析构函数。如下图所示,叫做浅拷贝,把a值赋给b,此时只是b指针与a指针指向相同,b指针原本的内存储存就没有办法找到了,发生了内存泄漏。
在这里插入图片描述

拷贝构造函数,传入的参数就是它自己那个类型。函数,首先创造一个足够的空间来放蓝本。

String::String(const String& str)
{
	m_data = new char[strlen(str.n_data)+1]; //分配空间
	strcpy(m_data, str.m_data); //拷贝内容
}

拷贝赋值函数,需要将原来的空间清空、再分配内存、再拷贝过来。

  1. 清空自身
  2. 分配足够的内存空间
  3. 拷贝内容

检测自我赋值,为了防止错误
在这里插入图片描述

output函数

操作符重载,定义<<输出符号。

在这里插入图片描述

堆、栈、内存管理

  • stack object的生命期:在作用域结束时就被清理。scope结束时,析构函数被自动调用
  • static local objects的生命期: static Complex c2(1,2);
    生命在作用域结束后仍存在,直到程序结束。
  • global objects :写在全局作用域之中(任何大括号之外的), 整个程序结束之后生命结束;

heap objects 的生命期:创建一个heap 对象,必须要delete该对象,否则会出现内存泄漏,即指针所指的heap object仍然存在,但指针p的生命却结束了,作用域之外再也见不到指针,也就没有就会delete 该指针。
在这里插入图片描述

new一个对象的顺序,拆分成三个动作:

  1. 使用operator new函数,内部就是调用c中的malloc()函数,分配内存的作用。
  2. 把complex类型转化为void
  3. 利用指针调用构造函数在这里插入图片描述
    delete一个对象的顺序
  4. 先调用构造函数
  5. 再释放内存
    在这里插入图片描述

以下每一个小空格是4个byte,complex类有两个double数值,所以分配8个byte,在调试模式下,绿色的内存空间上面多得到8x4个byte,下面多得到1x4个byte. 最上和最下的内存区域(红色)各分配4个byte,叫做cookie。
在VC中给的每一个内存块都是16的倍数,所以需要填补一些pad。
如果是在release模式下,就不需要debug head(灰色部分)。只需要上下cookie,是用来记录上下内存的大小,用于后面回收这段内存。
在这里插入图片描述

字符串的大小,内部只含一根指针,大小是4个byte。
下面表示用array new的分配内存的方式。
在这里插入图片描述
array new一定要搭配array delete
在这里插入图片描述

string.h

using namespace std;
#include <iostream>
using namespace std;

class String  //设计字符串,用指针可以实现动态分配,不用具体规定字符串的长度
{
public:
	//构造函数和拷贝构造函数没有返回类型
	String(const char* cstr = 0); //构造函数  
	String(const String& str); //拷贝构造函数,传进来的东西不会改变,所以const
	String& operator=(const String& str); //拷贝赋值函数,返回引用,因为本身就是存在的,不需要去创建
	//一般考虑传回的是reference,传回的东西存放的地方只要不是local object,就可以传回reference
	char* get_c_str() const{ return m_data; }

private:
	char* m_data; //class中有pointer member 所以需要考虑big three。
};

inline
String::String(const char* cstr = 0) //构造函数
{
	if (cstr) {
		m_data = new char[strlen(cstr) + 1];
		strcpy(m_data, cstr);
	}
	else { // 未指定初值
		m_data = new char[1]; *m_data = '\0';
	}
}

inline
String::~String()  //析构函数
{
	delete[] m_data; //array new要用 array delete
}

inline
String::String(const String& str)  //拷贝构造函数
{
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data, str.m_data);
}

inline
String& String::operator=(const String& str)   //拷贝赋值函数
{
	if (this == &str)
		return *this;     //判断是否是自我赋值
	delete[] m_data;
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data, str.m_data);
	return *this;  //*this是传出去的东西,接收的是返回的东西String&,传出去的东西不用管接收方的返回类型
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值