【C++侯捷】面对对象高级编程(三)
【C++侯捷】面对对象高级编程(三)
主要内容:拷贝构造、拷贝复制、析构
复习complex的构建过程
头文件的编写
#ifndef __COMPLEX__
#define __COMPLEX__
class complex
{
public:
//构造函数
complex(double r = 0,double r = o)
: re(r), im(r)
{}
//成员函数方法
private:
//成员变量
};
#endif
拷贝构造、拷贝复制、析构
class String
{
public:
String(const char * cstr = 0);
String(const String & str); //拷贝构造
String & operator = (const String& str);//拷贝赋值
~String(); //析构函数
char* get_c_str() const {return m_data;}//inline funtion
private:
char* m_data;
};
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; //清理;动态内存这里需要清理,否则会造成内存泄漏。像之前提到的value则不必。
}
应用
{
String s1(); //1
String s2("hellow"); //2 这两个在离开作用域的时候析构函数会自动消逝掉
String* p = new String("hellow"); //动态创建
delete p;
}
class with pointer members 必须有copy ctor 和copy op= (拷贝构造、拷贝赋值)
带有指针的类成员函数中必须有拷贝构造和拷贝复制
如果自己不去定义,编译器将默认使用default copy ctor 和 default op=,
会造成一下问题
即,ab只是两个指针,这样会造成b指针和a指针指向同一块内存空间,b原指向的内存空间则成了“孤儿”(内存泄漏),会出现问题,(比如如果将来通过a去更改,则b也会受影响)这也不是我们想要的结果,这样的称为“浅拷贝”。
深拷贝就是copy ctor 和copy op要做的事情。
copy ctor(拷贝构造函数)
inline
String::String(const String& str) //传入
{
m_data = new char[strlen(str.m_data) + 1]; //先开辟一段存放蓝本的内存空间
strcpy(m_data, str.m_data);
}
实例
{
String s1("hellow");
String s2(s1); //以s1为蓝本创建s2
//String s2 = s1; //将s1赋值给s2,同时创建s2对象;需调用构造函数
}
copy assignment operator(拷贝赋值函数)
inline
String& String::operator=(const String& str)
{
if(this == this == &str)
return *str; //检测自我赋值
delete[] m_data; //先清空原有
m_data = new data[strlen(str.m_data) + 1]; //创造相同空间
strcpy(m_data, str.m_data);
return *this;
}
实例
{
String s1("hellow");
String s2(s1);
s2 = s1;
}
一定要在operator操作中检测是否自我赋值
否则,第一步清空将清空原有的内存空间!!!不只是效率问题。
output函数
#include <iostream>
ostream& operator<<(ostream& os, const String& str) //全局函数
{
os << str.get_c_str();
return os;
}
{
String s1("hellow ");
cout << s1;
}
堆,栈与内存管理
所谓stack(栈),所谓heap(堆)
-
Stack,是存在于某作用域(scope)的一块内存空间(memory space)。例如当你调用函数,函数本身即会形成一个stack用来放置它所接收的参数,以及返回地址。在函数本体(function body)内声明的任何变量,其所使用的内存都取自上述stack。
-
Heap,或谓system heap,是指由操作系统提供的一块global内存空间,程序可\(动态分配\)(dynamic allocated)从某中获得若干区块(blocks)。
class Complex{ ...};
...
{
Complex c1(1,2); //c1所占用的空间来自stack,随着离开作用空间会自动消逝
Complex* p = new Complex(3); //此处是个临时对象,可在任何地方动态创建,其所占用的空间仍是以new自heap动态分配而得,并由p指向,需要手动释放
}
stack objects的生命期
上述c1便是所谓stack object,其生命在作用域结束之际结束(调用析构函数),这种作用域内的object,又称为auto object,因为它会被自动清除。
static local objects的生命期
class Complex{ ... };
{
static Complex c2(1,2);
}
c2
便是所谓static object
,其生命在作用域结束之后仍然存在,直到整个程序结束。
global objects的生命期
class Complex{... };
...
Complex c3(1,2);
int main()
{
...
}
一直有效直至程序结束。可把他视为一种static object。
heap objects的生命期
new: 先分配memory,再调用ctor
delete:先调用dtor,在释放memory
动态分配所得的内存块(memory block),in VC
8.堆,栈与内存管理(30:00)
动态分配所得的array
array new 与array delete
若在动态创建对象是使用的是
{
m_data= new char[strlen(str)+1]; //使用中括号形式
}
那么在销毁时要使用
{
deletep[] m_data;
}
不然会出错
详细
3是vc做法,记录array个数,和上面内存分配不一样