程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++拷貝構造函數與拷貝賦值操作符的問題

c++拷貝構造函數與拷貝賦值操作符的問題

編輯:C++入門知識

寫了一個String的類,沒有拷貝構造函數,但是有拷貝賦值操作符。

代碼:

01
#include <iostream>
02
#include <cstring>
03
using namespace std;
04
 
05
class String
06
{
07
public:
08
        String():data(0){ cout << "String()" << endl; }
09
        String(const char *str):data(0)
10
        { 
11
                int len = strlen(str);
12
                data = new char[len + 1];
13
                strcpy(data, str);
14
                cout << "String(char*)" << endl;
15
         } 
16
/×      String(const String &str):data(0)
17
        { 
18
                if (this != &str)
19
                { 
20
                        delete [] data;
21
                        data = new char[strlen(str.data) + 1];
22
                        strcpy(data, str.data);
23
                } 
24
                cout << "String(String&)" << endl;                         
25
        } 
26
×/
27
        ~String()
28
        { 
29
                cout << "~String()" << data << endl;
30
                delete [] data;
31
        } 
32
 
33
        String& operator=(const String &str)
34
        {
35
                if (this != &str)
36
                {
37
                        delete [] data;
38
                        data = new char[strlen(str.data) + 1];
39
                        strcpy(data, str.data);
40
                }
41
                cout << "=(String&)" << endl;
42
                return *this;
43
        }
44
 
45
        String& operator=(const char *ch)
46
        {
47
                if (ch)
48
                {
49
                        delete [] data;
50
                        data = new char[strlen(ch) + 1];
51
                        strcpy(data, ch);
52
                }
53
                cout << "=String(char*)" << endl;
54
                return *this;
55
        }
56
        void show()
57
        {
58
                if (data)
59
                        cout << data << endl;
60
                else
61
                        cout << "data is null" << endl;
62
        }
63
private:
64
        char *data;
65
};
01
int main(void)
02
{
03
        String s;
04
        s = "hello world!";
05
        s.show();
06
        String ss = s;
07
        ss.show();
08
       
09
        return 0;
10
}
 運行會出現:www.2cto.com

1
String()
2
=String(char*)
3
hello world!
4
hello world!
5
==(String&, String&)
6
ss is equal s
7
~String()hello world!
8
~String()
1
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x08ee2008 ***
2
======= Backtrace: =========
3
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x17b591]。。。。。。。。
這樣的錯誤。

開始一頭霧水,怎麼也不應該出現這樣的問題。後來發現原因在於:

1
String ss = s;
開始我以為這行代碼會調用拷貝賦值操作符的函數,但是他卻沒有調用。因為這行代碼是初始化ss,而不是賦值。他會去調用拷貝構造函數。加上拷貝構造函數問題就可以解決了。或者不加但是這樣

1
//String ss = s;
2
String ss;
3
ss = s;
也可以。
初始化與賦值的問題在這樣的情況下也有區別:

1
class Clazz
2
{
3
public:
4
  Clazz(const stirng &str):data(str){} // 初始化
5
//  Clazz(const string &str){data = str;} // 賦值
6
private:
7
  string data;
8
};
在初始化列表中,data會被直接初始化為str,即直接調用string的拷貝構造函數。
在賦值的情況下,

1
Clazz(const string &str){data = str;}
會被轉換成類似這樣的形式:
1
Clazz(const string &str):data(){data = str;}
即data的初始化分成兩步,先調用string的默認構造函數,然後在調用一次拷貝賦值操作符。
所以如果可以,盡量將成員的初始化放在初始化列表中是一個不錯的選擇。

在《c++ primer》中是這樣說的,一般情況下,初始化比賦值的效率要高。


摘自 Orion的博客

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved