字符串class
字符串创建的时候都是创建一个指针,因为不知道字符串要有多大,等知道后,再分配相应的空间给字符串
class String
{
public:
...
private:
char* m_data; //在字符串里放指针,是因为这样可以以动态分配的方式建立字符串
};
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; //在字符串里放指针,是因为这样可以以动态分配的方式建立字符串
//因为有指针,所以要有析构
};
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';
}
}
如果类带指针,一定要写拷贝构造和拷贝赋值还有析构,也就是big3
拷贝构造
public:
String(const char* cstr = 0);
String(const String& str);//拷贝函数,作为构造函数,接收的是自己这个类型
inline
String::String(const String& str)//拷贝构造函数,因为是构造函数,所以没有返回值
{
m_data = new char[strlen(str.m_data) + 1]; //可以直接取另一个object中的private变量,因为互为友元
strcpy(m_data, str.m_data); //深拷贝
}
拷贝赋值
public:
String(const char* cstr = 0);
String& operator=(const String& str); //拷贝赋值
inline String&
String::operator=(const String& str) //拷贝赋值函数,这里的&表示reference,在typename的后面
{
if (this == &str) return *this; //检测自我赋值,同时避免两个指针本来指向同一个东西时,还使
//用了拷贝赋值而出错,这里的&是取地址,在object后面
delete[] m_data; //先清空=号左边,也就是自己的东西
m_data = new char[strlen(str.m_data) + 1]; //然后分配一块和右边一样大的空间
strcpy(m_data, str.m_data); //再把右边的东西放到左边
return *this;
}
析构函数
public:
String(const char* cstr = 0);
~String(); //析构函数
inline
String::~String()
{
delete[] m_data;
}
不使用new属于在栈中分配内存,在栈中内存由系统自动的去分配和释放,无需写delete,另外有一点发现,就是栈中对象的释放顺序,是后定义的先释放。而使用new创建的指针对象是在堆中分配内存,当不需要该对象时,需要我们手动的去释放,否则会造成内存泄漏。