C++ allows the programmer to define how objects are to be copied, moved, assigned and destroyed. Together these are known as copy control.

拷贝控制的基础 

一、复制初始化

复制初始化 de 使用

Ref: C++的一大误区——深入解释直接初始化与复制初始化的区别

#include <iostream>
#include <cstring>
using namespace std;
 
class ClassTest
{
public:
  ClassTest()
  {
    c[0] = '\0';
    cout<<"ClassTest()"<<endl;
  }
  ClassTest
& operator=(const ClassTest &ct)   {     strcpy(c, ct.c);     cout<<"ClassTest& operator=(const ClassTest &ct)"<<endl;     return *this;   }
  ClassTest(
const char *pc)   {     strcpy(c, pc);     cout<<"ClassTest (const char *pc)"<<endl;   }
  ClassTest(const ClassTest& ct)   {     strcpy(c, ct.c);     cout<<"ClassTest(const ClassTest& ct)"<<endl;   }
private:   char c[256]; };

[c++] Copy Control 

1、ClassTest ct1("ab");
这条语句属于直接初始化,它不需要调用复制构造函数,直接调用构造函数ClassTest(const char *pc),所以当复制构造函数变为私有时,它还是能直接执行的。
 
2、ClassTest ct2 = "ab";
这条语句为复制初始化,它首先调用构造函数ClassTest(const char *pc)函数创建一个临时对象,然后调用复制构造函数,把这个临时对象作为参数,构造对象ct2;所以当复制构造函数变为私有时,该语句不能编译通过。
 
3、ClassTest ct3 = ct1;
这条语句为复制初始化,因为ct1本来已经存在,所以不需要调用相关的构造函数,而直接调用复制构造函数,把它的值复制给对象ct3;所以当复制构造函数变为私有时,该语句不能编译通过。
 
4、ClassTest ct4(ct1);
这条语句为复制初始化,因为ct1本来已经存在,直接调用复制构造函数,生成对象ct1的副本对象ct4。所以当复制构造函数变为私有时,该语句不能编译通过。
 
注:第4个对象ct4与第3个对象ct3的创建所调用的函数是一样的,但是本人却认为,调用复制函数的原因却有所不同。因为直接初始化是根据参数来调用构造函数的,如ClassTest ct4(ct1),它是根据括号中的参数(一个本类的对象),来直接确定为调用复制构造函数ClassTest(const ClassTest& ct),这跟函数重载时,会根据函数调用时的参数来调用相应的函数是一个道理;而对于ct3则不同,它的调用并不是像ct4时那样,根据参数来确定要调用复制构造函数的,它只是因为初始化必然要调用复制构造函数而已。它理应要创建一个临时对象,但只是这个对象却已经存在,所以就省去了这一步,然后直接调用复制构造函数,因为复制初始化必然要调用复制构造函数,所以ct3的创建仍是复制初始化。
 
5、ClassTest ct5 = ClassTest();
这条语句为复制初始化,首先调用默认构造函数产生一个临时对象,然后调用复制构造函数,把这个临时对象作为参数,构造对象ct5。所以当复制构造函数变为私有时,该语句不能编译通过。

 

编译器暗中优化

编译会帮你做很多你看不到,你也不知道的优化,

"你看到的结果,正是编译器做了优化后的代码的运行结果,并不是你的代码的真正运行结果。"

 

二、访问权限

复制构造函数是可以由编译默认合成的,而且是公有的(public),编译器就是根据这个特性来对代码进行优化的。

如果你自己定义这个复制构造函数,编译则不会自动生成,虽然编译不会自动生成,但是如果你自己定义的复制构造函数仍是公有的话,编译还是会为你做同样的优化。

当它是私有成员时,编译器就会有很不同的举动,因为你明确地告诉了编译器,你明确地拒绝了对象之间的复制操作,所以它也就不会帮你做之前所做的优化,你的代码的本来面目就出来了。

 

public 的 复制构造函数

 #include <iostream>
 #include <algorithm>
 #include <vector>
 #include <string>
 
 using namespace std;
 
 class CExample
 {
     private:
         int a;
 
     public:
         CExample(int b) {
             a=b;
             printf("constructor is called\n");
         }

         CExample(const CExample & c) {
             a=c.a;
             printf("copy constructor is called\n");
         }
 
         ~CExample() {
             cout<<"destructor is called\n";
         }
 
         void Show()
         {
             cout<<a<<endl;
         }
 };
 
  int main(void)
 {
     CExample A(100);
 
     CExample B=A;
 
     CExample C=CExample(A);
 
     B.Show(); 
     return 0;
 }
View Code

相关文章:

  • 2022-02-03
  • 2022-12-23
  • 2021-06-25
  • 2021-08-13
  • 2022-12-23
  • 2021-09-07
  • 2022-01-22
  • 2021-10-28
猜你喜欢
  • 2021-11-28
  • 2021-08-20
  • 2021-08-19
  • 2022-12-23
  • 2021-10-30
  • 2021-12-13
相关资源
相似解决方案