posts - 183,  comments - 10,  trackbacks - 0

关于含有成员指针的类的复制控制

一个类中如果含有了指针成员,在不加任何措施的时候,复制类对象是做的位复制操作,即是所谓的浅拷贝,两个对象的指针式一样的值,指向同一块内存区。
这种情况下,当一个对象删除其成员指针指向的内存区后,另一个对象的指针成员指向的内存区也就被释放了。
如果第一个对象析构时删除了这个内存区,那么在第二对象析构时造成同一块内存多次被释放,程序崩溃。

解决这个问题有常规上有两种方法
一是,进行深拷贝,在拷贝构造函数和复制运算符中进行相应的内存分配和复制工作。析构的时候只是各自析构各自的。
二是,采用引用计数手段,在拷贝构造函数和复制运算符中对引用计数进行分析,多个复制对象的指针成员只指向同一个内存区,在最后一个对象析构的时候才最终将这个内存区释放掉。
引用计数的好处是,可以节省内存分配、拷贝、内存释放所带来的效率消耗,以及节省内存。

http://www.cppblog.com/jake1036/archive/2011/05/17/146594.html

浅拷贝

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 class str
 6 {
 7 private:
 8     char* s_;
 9 public:
10     str(const char* s = "")
11     {
12         s_ = new char[strlen(s) + 1];
13         if (s_ != 0)
14         {
15             strcpy(s_, s);
16         }
17     }
18     ~str()
19     {
20         delete [] s_;
21     }
22     char* s() const
23     {
24         return s_;
25     }
26 };
27 
28 ostream& operator << (ostream& outconst str& s)
29 {
30     out << s.s() << endl;
31     return out;
32 }
33 
34 int main()
35 {
36     str s1 = "123";
37     str s2(s1);
38     cout << s1 << endl;
39     cout << s2 << endl;
40 }

 


深拷贝
 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 class str
 6 {
 7 private:
 8     char* s_;
 9 public:
10     str(const char* s = "")
11     {
12         s_ = new char[strlen(s) + 1];
13         if (s_ != 0)
14         {
15             strcpy(s_, s);
16         }
17     }
18     str(const str& s)
19     {
20         s_ = new char[strlen(s.s_) + 1];
21         if (s_ != 0)
22         {
23             strcpy(s_, s.s_);
24         }
25     }
26     str& operator = (const str& s)
27     {
28         if (this != &s)
29         {
30             delete [] s_;
31             s_ = new char[strlen(s.s_) + 1];
32             if (s_ != 0)
33             {
34                 strcpy(s_, s.s_);
35             }
36         }
37         return *this;
38     }
39     ~str()
40     {
41         delete [] s_;
42     }
43     char* sr() const
44     {
45         return s_;
46     }
47 };
48 
49 ostream& operator << (ostream& outconst str& s)
50 {
51     out << s.sr() << endl;
52     return out;
53 }
54 
55 int main()
56 {
57     str s1 = "123";
58     str s2(s1);
59     cout << s1 << endl;
60     cout << s2 << endl;
61 }


引用计数
引用计数的实现是通过在类对象中增加一个指向 int 型的指针,这个指针指向的那个 int 即是计数,记录指针指向的那块内存被几个对象共用着。
采用引用计数,在构造函数、析构函数、拷贝构造函数、复制运算符中,都要对这个指向 int 的指针进行操作,并且需要判断指针指针指向 int 的变化情况,当为 0 时,则要释放掉指针指向的内存。
 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 class str
 6 {
 7 private:
 8     char* s_;
 9     int* pcount_;
10 public:
11     str(const char* s = "")
12     {
13         s_ = new char[strlen(s) + 1];
14         if (s_ != 0)
15         {
16             strcpy(s_, s);
17             pcount_ = new int;
18             if (pcount_ != 0)
19             {
20                 *pcount_ = 1;
21             }
22         }
23     }
24     str(const str& s)
25     {
26         s_ = s.s_;
27         pcount_ = s.pcount_;
28         ++(*pcount_);
29     }
30     str& operator = (const str& s)
31     {
32         if (this != &s)
33         {
34             --(*pcount_);
35             if (*pcount_ == 0)
36             {
37                 if (s_ != 0)
38                 {
39                     delete [] s_;
40                     s_ = 0;
41                 }
42                 delete pcount_;
43                 pcount_ = 0;
44             }
45             s_ = s.s_;
46             pcount_ = s.pcount_;
47             ++(*pcount_);
48         }
49         return *this;
50     }
51     ~str()
52     {
53         --(*pcount_);
54         if (*pcount_ == 0)
55         {
56             // cout << "test" << endl;
57             if (s_ != 0)
58             {
59                 delete [] s_;
60                 s_ = 0;
61             }
62             delete pcount_;
63             pcount_ = 0;
64         }
65     }
66     char* sr() const
67     {
68         return s_;
69     }
70 };
71 
72 ostream& operator << (ostream& outconst str& s)
73 {
74     out << s.sr() << endl;
75     return out;
76 }
77 
78 int main()
79 {
80     str s1 = "123";
81     str s2(s1);
82     cout << s1 << endl;
83     cout << s2 << endl;
84 }
85 



posted on 2011-07-22 17:20 unixfy 阅读(259) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理