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: 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.  
  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---

猜你喜欢

转载自www.linuxidc.com/Linux/2016-07/133148.htm