总:Classes的两个经典分类
- Class without pointer member(s)
complex
- Class with pointer member(s)
string
一. string class
#ifndef __MYSTRING__ string.h
#define __MYSTRING__
class String
{
...
};
String::function(...) ...
Global::function(...) ...
#endif
int main(){
String s1();
String s2("hello");
String s3(s1);
cout << s3 << endl;
s3 = s2;
cout << s3 <<endl;
}
二. Big Three, 三个特殊函数
- 一般创建一个字符指针,指向字符串。因为字符串的大小不确定。
- Big Three:拷贝构造、拷贝赋值、析构函数。
- 拷贝构造:输入参数为string类型。
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;}
private:
char* m_data;
}
三. ctor和dtor (构造函数和析构函数)
- new动态分配内存,所以需要在析构函数中 delete。
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;
}
{
String s1();
String s2("hello");
String* p = new String("hello");
delete p;
}
四. 必须有拷贝构造和拷贝赋值函数
五. 拷贝构造函数
inline
String:String(const String& str){
m_data = new char[ strlen(str.m_data) +1 ]
strcpy(m_data, str.m_data)
}
{
String s1("hello");
String s2(s1);
// String s2 = s1;
}
六. 拷贝赋值函数
- 把一个对象s1拷贝给另外一个对象s2。
- (1)先把s2清空,(2)再构造一块和s1相同大小的空间,(3)再拷贝回去。
inline
String& String::opeator=(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;
}
七. output函数
#include<iostream.h>
ostream operator<<(ostream& os, const String& str){
os<< str.get_c_str();
return os;
}
{
String s1("hello");
cout << s1;
}
八. stack 栈,heap堆
- Stack,存在于某作用域(scope)的一块内存空间。例如当你调用函数,函数本身会形成一个stack用来放置所接收的参数,以及返回地址。
- 在函数本体内声明的任何变量,其所使用的的内存块都取自stack。
- Heap, 或 system heap,指有操作系统提供的一块global内存空间,程序可以动态分配若干区块。
class Complex{...};
...
{
Complex c1(1, 2);
Complex* p = new Complex(3);
}
九. objects的生命期
class Complex{...};
...
{
Complex c1(1, 2);
}
- c1是stack object,其生命在作用域scope结束结束。这种作用域内的object,成为 auto object,因为会被自动清理。
class Complex{...};
...
{
static Complex c2(1, 2);
}
- c2是static object, 其声明在作用域(scope)结束之后仍然存在,直到整个程序结束。
class Complex {...};
...
Complex c3(1, 2);
int main(){
...
}
- c3是global object, 其声明在整个程序结束后才结束,也可以视为一种static object, 其作用域是整个程序。
class Complex {...};
...
{
Complex* p = new Complex;
....
delete p;
}
- p是heap object,其声明在deleted之后结束。
class Complex {...};
...
{
Complex* p = new Complex;
}
- 会出现内存泄露, p所指的heap object 仍然存在,但指针p的声明已经结束了,作用域之外也看不到p,没办法释放内存。
十. new: 先分配memory,再调用构造函数
Complex *pc;
void* mem = operator new( sizeof(Complex) ); //分配内存
pc = static_cast<Complex*>(mem); //转型
pc->Complex::Complex(1, 2); //构造函数
// Complex::Complex(pc, 1, 2);
十一. 先调用析构函数,再释放memory
delete ps;
String::~String(ps); //析构函数
operator delete(ps); //释放内存, 内部调用free(ps)
网友评论