歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++再議構造函數及復制構造函數深度復制

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: [email protected]
  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: [email protected]
  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: [email protected]
  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.  
  3. #include<iostream>
  4. using namespace std;
  5. class charin
  6. {
  7.         private:
  8.                 ..........
  9.         public:
  10.                 ..........
  11.                 charin(charin &); //加入
  12.                 .........
  13. };
     
     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---

Copyright © Linux教程網 All Rights Reserved