C++面向对象程序设计上 2 Class with pointer members

写一个String类,实现一下功能:

int main()
{
	String s1();
	String s2("hello");

	String s3(s2);
	cout<<s3<<endl;
	s3 = s2;
	
	cout<<s3<<endl;
}

1 Big Three 三个特殊函数

class String
{
public:
	String (const char* cstr = 0);//构造函数
	String (const String& str);//拷贝构造函数 返回类型就是String
	String& operator = (const String& str);//运算符重载 但是是拷贝重载
	~String();//析构函数
	char* get_c_str() const{return m_data;}
private:
	char* m_data;//使用指针,动态的创建空间
}

2 构造函数和析构函数

2.1 析构函数

inline 
String::String (const char* cstr = 0)
{
	if(cstr)
	{
		m_data = new char[strlen(str) + 1];
		strcpy(m_data , cstr);
	}
	else
	{
		m_data = new char[1];
		*m_data = '\0';
	}
}

inline 
String::~String()
{
	delete[] = m_data;//array new 必须搭配 array delete
}

class有指针,多半需要做动态分配,既然有了动态分配,对象死亡之前,析构函数被调用,把动态分配的内存释放

2.2 拷贝构造和拷贝赋值

class with pointer members 必须有 copy ctor和copy op=

原因:假设,String a = (“Hello”) String b = (“World”) 想要实现b = a
如果只是传统意义上b = a,那么仅仅只是把b指向字符串内容的指针,指向了a
这并不是我们想要的

2.2.1拷贝构造函数:

inline 
String :: String(const String& str)
{
	m_data = new char[strlen(str) + 1];
	strcpy(m_data,str.m_data);
}

2.2.2拷贝赋值函数

一个盒子a和一个盒子b,里面都放满东西。现在,要把b里的东西放到a
(1)清空a (2)b里开一个空间和a一样大(3)把a放进去

inline
String& String :: operator=(const String& str)
{
	if(this == &str)检测自我赋值,必写 否则执行下面三点
	会先杀掉自己,后面就没法执行了
	{
		return *this;
	}
	delete[] m_data;  (1)
	m_data = new char[strlen(str.m_data) + 1];(2)
	strcpy(m_data,str.m_data);(3)
}

2.3 output函数

重载 << 操作符 , 显然,重载为全局函数。

#include <iostream.h>
ostream& operator << (ostream& os , const String& str)
{
	os<<str.get_c_str();
把str的指针放到os
	return os;
}

3 stack and heap

class Complex{...};
...
{
	Complex c1(1,2);
	Complex* p = new Complex(3);
}

第一个 c1的创建,是一个local变量,在创建,离开这个作用于自动销毁
第二个c2是new了一个内存,由分配,必须手动delete

3.1stack object生命周期

c1便是如此,离开作用域就结束。又名 auto object,析构函数会被自动调用

3.2 static local objects 生命周期

class Complex{...};
...
{
	static Complex c2(1,2);
}

离开作用域后,c2依然存在,直到整个程序结束

3.3 global objects生命周期

class Complex{...};
...
Complex c3(1,2);
int main()
{}

c3在整个程序结束后才结束

3.4 heap objects

class Complex{...};
...
{
	Complex* p = new Complex(3);
	...
	delete p;
}

p在离开作用域后,p所指向的heap object还存在,但是P的生命结束了。内存还没有被释放。所以必须手动delete,否则会内存泄露

4 new 和 delete

4.1 new

先分配内存,再调用ctor(构造函数)

Complex* pc = new Complex(1 ,2);

分三步:

1void* mem  = operator new(sizeof(Complex));//operator new 本质就是 malloc(),分配内存2)pc = static_cast<Complex* >(mem);//转型 mem是void*,pc是Complex*3)pc->Complex::Complex(1,2);//构造函数

4.2 delete

先调用dtor,再释放memory
delete ps;
分两步:

1)String :: ~String(ps);2operator delete(ps);

首先第一步,看string析构函数干嘛的:

public:
...
String :: ~String()
{
	delete[]  m_data;
}
private:
char* m_data;

字符串只是一个指针,指向了一块区域,所以第一步,是先把字符串里动态分配的沙雕。第二步,才把字符串本身杀掉。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值