Item2:Know what functions C++ silently writes and calls--了解C++默默编写并调用了哪些函数

来源:互联网 发布:薛之谦真实人品 知乎 编辑:程序博客网 时间:2024/06/05 15:57

假设你重新定义String类如下:

class String{  };

这就如同你写下了这样的代码:

class String

{

    String() {....}               //default构造函数

    String(const String& rhs)  {....}  //copy构造函数

    ~String() {....}   // 析构函数  为非non-virtual 可参考item:Declar destructors virtual in polymorphic base classes

    String& operator=(const String& rhs) {....}  // copy assignment操作符

};

所以我们定义一个如上的空类后、也可以如下方式使用而不提示错误:

String str1;    //调用default 构造函数

String str2(str1);   //调用copy构造函数

str2 = str1;      //调用copy assignment操作符

 

主要考虑copy构造函数和copy assignment操作符 两个函数

编译器创建的版本只是单纯的将来源对象的每一个non-static成员变量拷贝到目标对象。这是所谓的浅复制。

 

然而用默认的这些函数存在着很大的隐患,如下:

当我们的成员变量是指针的时候、例如下面一个类:

class A

{

public:

    A(const char* str){p str;}

private:

    char* p;

};

调用以下代码:

A  a1(“I am a student”);

A  a2;

a2 a1;

我们看看会出什么情况、运行代码后、编译器会为类A自动生成copy assignment操作符、执行如下代码:a2p =a1p   这将会产生如下问题:

1a2p所指的原有的内存没有释放、造成内存泄漏。

2a2pa1p 指向同一块内存、如有一方变动者都会影响另一方。

3、在对象析构时、p所指的内存将释放两次。

 

这个时候需要我们自己重新对这些函数进行定义、实现对指针所指向对象的克隆(这是所谓的深复制)

 这个时候就需要我们自己为这四大函数重新进行定义:

还是以String 为例:

#include <iostream>

using std::ostream;

using std::endl;

using std::cout;

 

class String

{

 

public:

       friend ostream& operator << (ostream& os, const String& s);

       String(const char *str = NULL);   //constructor

       String(const String &other);  //copy constructor

       ~String(void);               //destructor

       String& operator = (const String &other);          // operator =

                                         

private:

       char* m_data;

};

 

ostream& operator<<(ostream& os, const String& s)

{

       os << s.m_data;

       return os;

}

 

String::String(const char *str)

{

       if(str == NULL)

       {

              m_data = new char[1];

              if(!m_data)

              {

                     cout << "memory distribute error/n";

                     exit(1);

              }

       }

       else

       {

              m_data = new char[strlen(str) + 1];

              strcpy(m_data, str);

       }

}

 

String::String(const String& other)             //copy constructor

{

       m_data = new char[strlen(other.m_data) + 1];

       strcpy(m_data, other.m_data);

}

 

String::~String(void)                          //destructor

{

       delete []m_data;

}

 

String & String::operator = (const String &other)       //operator =

{

       if(this == &other)

              return* this;

 

       delete [] m_data;

 

       m_data = new char[strlen(other.m_data) + 1];

       strcpy(m_data, other.m_data);

 

       return* this;

}

 

 

int main()

{

       String a("I am a student");    // call constructor

       String b(a);            //call copy constructor

       String c = a;          //call operator =

 

       cout << a << ' ' << b << ' ' << c << endl;

       return 0;

}    

 

最后请记住:

编译器可以暗自为class创建default构造函数、copy构造函数、copy assignment操作符、以及析构函数。在成员变量中存在指针的时候,一定要自己重新定义这四大函数。

原创粉丝点击