灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:3365回复:0

[C++技术]c++拷贝构造函数与拷贝赋值操作符的问题

楼主#
更多 发布于:2012-09-06 11:32


写了一个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.atcpu.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》中是这样说的,一般情况下,初始化比赋值的效率要高。


喜欢0 评分0
游客

返回顶部