Big Three(拷贝构造,拷贝复制,析构)

class String 
{
  public:
    String (const char* cstr = 0);    // 构造函数,默认初值为0
    String (const String& str);       // 接受的值为类本身,因此为拷贝构造函数
    String& operator=(const String& str);  // = 号重载,拷贝赋值函数
    ~String();        // 析构函数,类死亡时自动调用
    char* get_c_str() const { return m_data; }

  private:
    char* m_data; 
}

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

  String s3(s1);      // 拷贝构造,类还未存在
  cout << s3 << endl;
  s3 = s2;            // 拷贝赋值,类已经存在

  cout << s3 << endl;
}
inline
String::String(const char* cstr = 0)
{
  if (cstr) {               // 指定初值
    m_data = new char[strlen(cstr) + 1];    // 分配传进来的长度+ '\0' 的空间
    strcpy(m_data, cstr);   // 复制  
  }
  else {                    // 未指定初值
    m_data = new char[1];
    *m_data = '\0';
  }
}

inline
String::~String()
{
  delete[] m_data;      // 将原来分配的内存释放
}
1. String p1("hello");                   //栈中分配内存

2. String p2 = String("hello");       //栈中分配内存,跟方法1相同,是方法1的完整模式

3. String *p3 = new String("hello");    //堆中分配内存

**
方法1、2中都是在栈中分配内存,在栈中内存由系统自动的去分配和释放,释放的顺序也和栈一样,后定义的先释放。
**

**
而使用new创建的指针对象是在堆中分配内存,当不需要该对象时,需要我们手动的去释放,否则会造成内存泄漏。
**

深拷贝,浅拷贝

如果类中有指针成员,则必须写拷贝构造和拷贝赋值函数。

假设 指针a -> "hello", 指针b -> "world",当执行 b = a 时,则变成 b 指向 a,造成 "world" 无人指向,发生了内存泄漏,而"hello" 被 a 和 b 同时指向的情况,那么将来一旦改变 a ,b 也会发生改变。那么,这种拷贝称之为 “浅拷贝”

深拷贝即为我们自己写的拷贝函数:

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

inline
String& String::operator=(const String& str)  // 拷贝赋值
{
  if(this == &str)    // 有可能是自己赋值给自己(比如引用),如果不写这句,那么delete就是它自己,下面全错
    return *this;

  delete[] m_data;    // 先将自己删除
  m_data = new char[ strlen(str.m_data) + 1 ];  // 重新创建和右边一样大的空间
  strcpy(m_data, str.m_data);     // 重新赋值
  return *this;
}