与构造函数一样,析构函数也是一种特殊的函数。构造函数在实例化对象时被调用,而析构函数 在对象销毁时自动被调用。

注意:

因为析构函数是在对象摧毁时自动调用 当前函数内(作用域)return 时会自动调用。

所以要注意浅复制时存在的问题

1. 浅复制

在一个程序中 如果创建一个 函数 参数为一个类 且存在 delete 的析构函数 会存在因为 析构函数产生的错误

#include <iostream>
#include <string.h>
using namespace std;

class MyString
{
private:
   char* buffer;

public:
   MyString(const char* initString) // Constructor
   {
      buffer = NULL;
	  if(initString != NULL)
      {
         buffer = new char [strlen(initString) + 1];
         strcpy(buffer, initString);
      }
   }

   ~MyString() // Destructor
   {
      cout << "Invoking destructor, clearing up" << endl;
      delete [] buffer;
   }

   int GetLength() 
   { return strlen(buffer); }

   const char* GetString()
   { return buffer; }
};

void UseMyString(MyString str)
{
   cout << "String buffer in MyString is " << str.GetLength();
   cout << " characters long" << endl;

   cout << "buffer contains: " << str.GetString() << endl;
   return;
}

int main()
{
   MyString sayHello("Hello from String Class");
   UseMyString(sayHello); 

   return 0;
}

当程序运行时 因为函数 UseMyString(MyString str) 传入的参数为对象本身,UseMyString(sayHello); 传入的类 sayHello 被赋值给 str 局部变量。 指向的时同一个类 所以str.buffer 和 satHello.buffer 指向同一个地址(内存)。所以在函数 UseMyString(MyString str)运行完返回时 会调用 str 的析构函数 从而 sayHello.buffer 会被 delete掉

当 main函数运行完后 会有一个 return 但是当return 时会调用 sayHello的析构函数 delete sayHello.buffer 但是 str调用析构函数的时候 buffer 已经被 delete 所以会报错

Function(类做为参数) 这个时候 指向同一个 内存。

2. 赋值构造函数

如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。

为了避免这个 错误 一般利用 复制构造函数 传入 类的引用 然后将申请的

#include <iostream>
#include <string.h>
using namespace std;

class MyString
{
private:
   char* buffer;

public:
   MyString() {}
   MyString(const char* initString) // constructor
   {
      buffer = NULL;
      cout << "Default constructor: creating new MyString" << endl;
      if(initString != NULL)
      {
         buffer = new char [strlen(initString) + 1];
         strcpy(buffer, initString);

         cout << "buffer points to: 0x" << hex;
         cout << (unsigned int*)buffer << endl;
      }
   }

   MyString(const MyString& copySource) // Copy constructor
   {
      buffer = NULL;
     cout << "Copy constructor: copying from MyString" << endl;
      if(copySource.buffer != NULL)
      {
         // allocate own buffer 
         buffer = new char [strlen(copySource.buffer) + 1];

         // deep copy from the source into local buffer
         strcpy(buffer, copySource.buffer);

         cout << "buffer points to: 0x" << hex;
         cout << (unsigned int*)buffer << endl;
      }
   }

   // Destructor
   ~MyString()
   {
      cout << "Invoking destructor, clearing up" << endl;
      delete [] buffer;
   }

   int GetLength() 
   { return strlen(buffer); }

   const char* GetString()
   { return buffer; }
};

void UseMyString(MyString str)
{
   cout << "String buffer in MyString is " << str.GetLength();
   cout << " characters long" << endl;

   cout << "buffer contains: " << str.GetString() << endl;
   return;
}

int main()
{
   MyString sayHello("Hello from String Class");
   UseMyString(sayHello);

   return 0;
}

复制构造函数

MyString(const MyString& copySource) // Copy constructor
   {
      buffer = NULL;
     cout << "Copy constructor: copying from MyString" << endl;
      if(copySource.buffer != NULL)
      {
         // allocate own buffer 
         buffer = new char [strlen(copySource.buffer) + 1];

         // deep copy from the source into local buffer
         strcpy(buffer, copySource.buffer);

         cout << "buffer points to: 0x" << hex;
         cout << (unsigned int*)buffer << endl;
      }
   }