c++拷贝构造函数与拷贝赋值操作符的问题

写了一个String的类,没有拷贝构造函数,但是有拷贝赋值操作符。

代码:

#include <iostream>
#include <cstring>
using namespace std;

class String
{
public:
        String():data(0){ cout << "String()" << endl; }
        String(const char *str):data(0)
        {   
                int len = strlen(str); 
                data = new char[len + 1]; 
                strcpy(data, str);
                cout << "String(char*)" << endl;
         }   
/×      String(const String &str):data(0)
        {   
                if (this != &str)
                {   
                        delete [] data;
                        data = new char[strlen(str.data) + 1]; 
                        strcpy(data, str.data);
                }   
                cout << "String(String&)" << endl;                           
        }   
×/
        ~String()
        {   
                cout << "~String()" << data << endl;
                delete [] data;
        }   

        String& operator=(const String &str)
        {
                if (this != &str)
                {
                        delete [] data;
                        data = new char[strlen(str.data) + 1];
                        strcpy(data, str.data);
                }
                cout << "=(String&)" << endl;
                return *this;
        }

        String& operator=(const char *ch)
        {
                if (ch)
                {
                        delete [] data;
                        data = new char[strlen(ch) + 1];
                        strcpy(data, ch);
                }
                cout << "=String(char*)" << endl;
                return *this;
        }
        void show()
        {
                if (data)
                        cout << data << endl;
                else
                        cout << "data is null" << endl;
        }
private:
        char *data;
};
int main(void)
{
        String s;
        s = "hello world!";
        s.show();
        String ss = s;
        ss.show();
       
        return 0;
}           

 运行会出现:

String()
=String(char*)
hello world!
hello world!
==(String&, String&)
ss is equal s
~String()hello world!
~String()
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x08ee2008 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x17b591]。。。。。。。。

这样的错误。

开始一头雾水,怎么也不应该出现这样的问题。后来发现原因在于:

String ss = s;

开始我以为这行代码会调用拷贝赋值操作符的函数,但是他却没有调用。因为这行代码是初始化ss,而不是赋值。他会去调用拷贝构造函数。加上拷贝构造函数问题就可以解决了。或者不加但是这样

//String ss = s;
String ss;
ss = s;

也可以。

初始化赋值的问题在这样的情况下也有区别:

class Clazz
{
public:
  Clazz(const stirng &str):data(str){} // 初始化
//  Clazz(const string &str){data = str;} // 赋值
private:
  string data;
};

在初始化列表中,data会被直接初始化为str,即直接调用string的拷贝构造函数。

在赋值的情况下,

Clazz(const string &str){data = str;}

会被转换成类似这样的形式:

Clazz(const string &str):data(){data = str;}

即data的初始化分成两步,先调用string的默认构造函数,然后在调用一次拷贝赋值操作符。

所以如果可以,尽量将成员的初始化放在初始化列表中是一个不错的选择。

在《c++ primer》中是这样说的,一般情况下,初始化比赋值的效率要高。

 

 

你可能感兴趣的:(c++拷贝构造函数与拷贝赋值操作符的问题)