//string.h
#ifndef __MYSTRING__
#define __MYSTRING__
#define _CRT_SECURE_NO_WARNINGS
class String
{
public:
//默认构造函数,并设置默认值
String(const char* cstr = 0);
//Big Three三大函数:拷贝构造,拷贝赋值,析构。编译器会自动给出三大函数。
//对于class with pointer,三大函数需要自己写,不能使用编译器给的默认版本。
//不然会出现内存泄漏(memory leak)和别名(alias):多个指针指向同一块内存。
//1. 拷贝构造
String(const String& str);
//2. 拷贝赋值,返回值为String&,可以满足连串赋值的操作
String& operator=(const String& str);
//3. 析构
~String();
char* get_c_str() const { return m_data; }
private:
char* m_data;
};
#include <cstring>
inline
String::String(const char* cstr)
{
//对传入的指针进行判断
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;
}
inline
String& String::operator=(const String& str)
{
//检查自我赋值(self assignment)
//1. 提高效率
//2. 正确性,如果自我赋值会出错
if (this == &str)
return *this;
//经典写法1-2-3
//1. 先清空自己指向的内存
delete[] m_data;
//2. 分配需要的内存
m_data = new char[strlen(str.m_data) + 1];
//3. 最后拷贝数据
strcpy(m_data, str.m_data);
return *this;
}
//深拷贝,编译器自动给出的为浅拷贝
inline
String::String(const String& str)
{
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
#include <iostream>
using namespace std;
// <<的重载必须写为非成员函数
// 如果写成成员函数,使用者则需要这样写:string << cout; 这样不符合常用习惯。
ostream& operator<<(ostream& os, const String& str)
{
os << str.get_c_str();
return os;
}
#endif
//string-test.cpp
#include "string.h"
int main()
{
String str1;
String str2("hello str2");//默认构造
String str3 = "hello str3";//默认构造
String str4(str2);//拷贝构造
String str5 = str4;//拷贝构造,同上
str1 = str2;//赋值构造
//重载<<
cout << "str1:" << str1 << endl;
cout << "str2:" << str2 << endl;
cout << "str3:" << str3 << endl;
cout << "str4:" << str4 << endl;
cout << "str5:" << str5 << endl;
//new:先分配memory,再调用ctor。
String* pstr = new String[3];
//编译器将上面语句翻译为下面三个动作
//1. void* mem = operator new(sizeof(String)*3); 其内部调用malloc(n);
//2. pc = static_cast<String*>(mem);
//3. pc->String::String();调用三次构造
pstr[0] = str1;
pstr[1] = str2;
pstr[2] = str3;
cout << "pstr[1]:" << pstr[0] << endl;
cout << "pstr[2]:" << pstr[1] << endl;
cout << "pstr[3]:" << pstr[2] << endl;
//delete:先调用dtor,再释放memory;
delete[] pstr;
//编译器将上面语句翻译为下面两个动作
//1. String::~String(pstr);调用三次析构。
//2. operator delete(pstr); 其内部调用free(pstr);
}