C++再議建構函式及複製建構函式深度複製

gaopengtttt發表於2016-06-29
1、一般建構函式
如果沒有提供任何建構函式,建立一個什麼都不做的建構函式
如:
test::test()
{}
如果希望編譯器不使用這種預設的建構函式
可以自己定義預設建構函式
test::test()
{
  ...........;
}
當然也可以自己傳入值定義建構函式
test::test(const char* tin)
{
  ...........;
}


2、複製建構函式
它用於將一個物件複製到一個新建立的物件中,類的複製建構函式原型如下:
class_name(const class_name &);
關於複製建構函式下面幾種情況會使用到:
test my1(my); 顯示呼叫,my1是和my一樣的副本
test my1 = test(my); 顯示呼叫,my1是和my一樣的副本
test my1 = my; 隱試呼叫,my1是和my一樣的副本
void tf1(test t1);函式傳值生成臨時的類物件在函式中使用
test *p = new test(my);未測試
簡單的說程式生成了物件的副本,編譯器都會使用複製建構函式;既然是副本我們可以想象如果
類中定義的是指標型別,那麼指標指向的是同一片位置。如果此時呼叫解構函式會重複的釋放
同一片記憶體區域,同時如果不定義複製建構函式,那麼某些計數器將不你能正常工作。

另外我們注意同一段函式中如果類中有靜態物件如下:
private:
static int num_s;
使用
int charin::num_s = 0; 
那麼在呼叫這個類的函式中多次呼叫它使用值是共享的因為是同一塊記憶體區域。這個其實和一般
的靜態內部變數沒什麼兩樣

我們來看一段程式碼

點選(此處)摺疊或開啟

  1. ::::::::::::::
  2. c2.h
  3. ::::::::::::::
  4. /*************************************************************************
  5.   > File Name: c2.h
  6.   > Author: gaopeng
  7.   > Mail: gaopp_200217@163.com
  8.   > Created Time: Fri 24 Jun 2016 01:47:19 AM CST
  9.  ************************************************************************/

  10. #include<iostream>
  11. using namespace std;

  12. class charin
  13. {
  14.         private:
  15.                 static int num_s;
  16.                 char* sin;
  17.                 int len;
  18.         public:
  19.                 charin(void);
  20.                 charin(const char *);
  21.                 //charin(charin &);
  22.                 ~charin(void);
  23.                 friend std::ostream & operator<<(std::ostream &,const charin &);
  24. };
  25. ::::::::::::::
  26. cf.cpp
  27. ::::::::::::::
  28. /*************************************************************************
  29.     > File Name: cf.cpp
  30.     > Author: gaopeng
  31.     > Mail: gaopp_200217@163.com
  32.     > Created Time: Fri 24 Jun 2016 01:59:13 AM CST
  33.  ************************************************************************/

  34. #include<iostream>
  35. #include<string.h>
  36. #include"c2.h"
  37. using namespace std;

  38. int charin::num_s = 0;

  39. charin::charin(void)
  40. {
  41.         len = strlen("study c++")+1;
  42.         cout << len <<" mem alloc!"<<endl;
  43.         sin = new char[len];
  44.         strcpy(sin,"study c++");
  45.         num_s++;
  46.         cout << sin <<" in "<<num_s<<endl;
  47. }
  48. charin::charin(const char* sorstr )
  49. {
  50.         len = strlen(sorstr)+1;
  51.         cout << len <<" bytes mem alloc!"<<endl;
  52.         sin = new char[len];
  53.         strcpy(sin,sorstr);
  54.         num_s++;
  55.         cout << sin <<" in "<<num_s<<endl;
  56. }
  57. charin::~charin(void)
  58. {
  59.         num_s--;
  60.         cout << len <<" bytes mem release!"<<endl;
  61.         cout << sin <<" out "<<num_s<<endl;
  62.         delete [] sin;
  63. }
  64. std::ostream & operator<<(std::ostream & os,const charin & cin)
  65. {
  66.         os << cin.sin;
  67.         return os;
  68. }

  69. ::::::::::::::
  70. main.cpp
  71. ::::::::::::::
  72. /*************************************************************************
  73.     > File Name: main.cpp
  74.     > Author: gaopeng
  75.     > Mail: gaopp_200217@163.com
  76.     > Created Time: Fri 24 Jun 2016 02:23:51 AM CST
  77.  ************************************************************************/

  78. #include<iostream>
  79. #include"c2.h"
  80. using namespace std;


  81. void chmi(charin );

  82. int main(void)
  83. {
  84.         const char *testc = "test123";
  85.         charin t1;
  86.         cout <<"test"<<endl;
  87.         charin t2(testc);
  88.         charin t3 = t2; //error
  89.         chmi(t2); //error

  90. }

  91. //error beacause pointer sin pointer same point;
  92. void chmi(charin a)
  93. {
  94.         cout<<"test here: "<<a<<endl;
  95. }
這段程式報錯如下:
gaopeng@bogon:~/CPLUSPLUS/part11/c2$ ./a.out 
10 mem alloc!
study c++ in 1
test
8 bytes mem alloc!
test123 in 2
test here: test123
8 bytes mem release!
 out 1
*** Error in `./a.out': double free or corruption (fasttop): 0x00000000021c1030 ***
Aborted (core dumped)

我使用的LINUX g++編譯器,可以看報錯double free or corruption,重複的釋放,其實這裡的計數器num_s也不能正常工作。
這種情況下我們必須要自己定義複製建構函式,使用深度複製而不是簡單的為指標型別資料複製指標的指向而已。
我們在程式中加入:

點選(此處)摺疊或開啟

  1. c2.h 加入

  2. #include<iostream>
  3. using namespace std;

  4. class charin
  5. {
  6.         private:
  7.                 ..........
  8.         public:
  9.                 ..........
  10.                 charin(charin &); //加入
  11.                 .........
  12. };
     
     cf.cpp加入新函式 複製建構函式
  1. charin::charin(charin &in)
  2. {
  3.         len = in.len;
  4.         sin = new char[len];
  5.     strcpy(sin,in.sin);
  6.         num_s++;
  7.         cout << len <<" bytes mem alloc!"<<endl;
  8.         cout << sin <<" deep copy in "<<num_s<<endl;
  9. }
接著我們再來跑一下我們的程式
10 mem alloc!
study c++ in 1
test
8 bytes mem alloc!
test123 in 2
8 bytes mem alloc!
test123 deep copy in 3
8 bytes mem alloc!
test123 deep copy in 4
test here: test123
8 bytes mem release!
test123 out 3
8 bytes mem release!
test123 out 2
8 bytes mem release!
test123 out 1
10 bytes mem release!
study c++ out 0

沒有問題了。

---endl---


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2121213/,如需轉載,請註明出處,否則將追究法律責任。

相關文章