一、Copy Constructor的构建操作

  就像 default constructor 一样,如果class没有申明一个 copy constructor,就会隐含的声明或隐含的定义一个。生成的 copy constructor 也分为 trivial 和 nontrivial 两种。只有 nontrivial 的实体才会被合成于程序之中。决定一个 copy constructor 是否为 trivial 的标准在于class是否展现出所谓的"bitwise copy semantics(语义上位逐次拷贝)"---展现出了就是trivial ,没的话就是 nontrivial !那么什么是 bitwise copy semantics,稍后会讲到。

  有四种情况下不要 Bitwise Copy semantics,其实是和生成 nontrivial default constructor 类似啦:

  1.当class内含一个 member object 而后者的class 声明有一个 copy constructor 时(不论是被 class 设计者明确地声明,还是背编译器合成)。

  2.当class继承自一个 base class 而后者存在有一个 copy constructor 时(再次强调,不论被声明或是被合成而得)。

  3.当声明一个或多个 virtual functions 时。

  4.当class派生自一个继承串链,其中有一个或多个virtual base classes时。

  综合是否生产 nontrivial 的 default constructor 和 copy constructor 的条件可看出:如果编译要做额外的事那么就需要生成 nontrivial 的 default constructor 和 copy constructor!

  现在来说说什么是:bitwise copy semantics !请看一个程序:

 

 #include <iostream>
#include <string> using namespace std; class A
{
public:
int i;
int *pi;
}; int main()
{
A a;
int i = ;
a.i = ;
a.pi = &i;
A b = a;
cout << "a.i: " << a.i << " b.i: " << b.i << endl;
cout << "a.pi address: " << a.pi << endl;
cout << "b.pi address: " << b.pi << endl;
return ;
}

  下面是输出结果!

  嗯,大家看到没,我的 class A 中没有任何和复制有关的代码,但是我在进行赋值操作 A b = a;后,b中的i 和 pi变量内的内容一模一样了,很显然:编译器在背后做了动作帮你把a的值复制给了b,这就是我要说的 bitwise copy semantics(语义上位逐次拷贝)---他将 a 中的 i 所在的内存中的内容 和 pi 本身所在的内存中的内容(注意我这里说的是pi本身所在的内存中的内容而不是pi所指的内存中的内容,请区别这两个意思)逐一的拷贝给 b 中的 i 所在的内存和 pi 本身所在的内存。位逐次拷贝因此得名!!!

  数值型的 i 是正确的复制了但是指针型的 pi 就不对了,他们所指向的地址居然相同,这显然不对!这和我们所期望的不一致,对吗?你肯定是想让 b 中的 pi 指向另外一块内存,只是这内存中的值和a 中的pi所指向的内存中的值一样罢了。并不是让指针本身相同!所以,bitwise copy (semantic 我稍后解释)还有另外一个名字:浅拷贝。顾名思义,编译器只是机械的、做一些简单的拷贝!当然与  bitwise copy(浅拷贝)相对应的是 memberwise(深拷贝)---这个也故名思议了,能达到你想要的效果,但是这个要你自己通过代码去实现!

  注意了哈:下面是我在看《深度探索C++对象模型》第二章 copy constructor 的构建时比较迷惑的地方,不知道大家有没有和我同样的疑惑呢,具体疑惑如下:

  书上给出了 Bitwise Copy Semantics的四个条件,就是我上面所说的哈!也就是不生成一个nontrivial copy constructor的条件!好,那么请看下面代码!

 #include <iostream>
#include <string> using namespace std; class A0
{
public:
A0(){}
A0(const A0&){}
}; class A
{
public:
int i;
int *pi;
A0 a0;
}; int main()
{
A a;
int i = ;
a.i = ;
a.pi = &i;
A b = a;
cout << "a.i: " << a.i << " b.i: " << b.i << endl;
cout << "a.pi address: " << a.pi << endl;
cout << "b.pi address: " << b.pi << endl;
return ;
}

  这个代码只是在 A 的前面定义了另一个类A0,然后A类中有一个 member object a0!大家来看看class A是否符合以上4个条件中的条件 1 呢( class A 的 member object a0 的 class 声明了一个 copy constructor)?那是不是不出现 bitwise copy semantic 呢?但是 i 和 pi 确实也拷贝过来了啊---看看运行结果就知道,结果和上面截图一样我就不贴出来了!这是为什么呢----这就是我迷惑的地方!那么我讲讲我的想法。

  也就是说满足以上四个条件之后进行的拷贝也进行了拷贝,只是这次不是从语义上(semantic)的 copy constructor 来进行拷贝了!而是从实际的 copy constructor 函数体中进行了拷贝,什么叫概念上?就是说之前那个class A进行的拷贝并没有合成一个nontrivial copy constructor来专门进行这个拷贝工作,所以说只是语义上(semantic)的!也就是说他确实是拷贝了,但不是通过合成那个nontrivial copy constructo来进行拷贝,我们把这种拷贝成为bitwise copy semantic!所以第二代吗中的class A 虽然满足了以上四个条件并进行了同样的bitwise copy,但这不能叫bitwise copy semantic,顶多只能叫bitwise copy啦!因为他合成了一个专门的nontrivial copy constructor,就不能叫语义上(semantic)了!

  如果大家理解了我说的那么相信大家在看《深度探索C++对象模型》第二章的copy constructor的构建操作时就不会那么迷茫了!

构造函数语义学之Copy Constructor构建操作(1)的更多相关文章

  1. 构造函数语义学之Copy Constructor构建操作(2)

    二.详述条件 3 和 4 那么好,我又要问大家了,条件1 和 2比较容易理解.因为member object或 base class 含有copy constructor.那么member objec ...

  2. 构造函数语义学之Default Constructor构建操作

    一.Default Constructor的构建操作 首先大家要走出两个误区: 1).任何class如果没有定义default constructor,就会被合成一个来. 2).便以其合成出来的def ...

  3. 深度探索C++对象模型之第二章:构造函数语意学之Copy constructor的构造操作

    C++ Standard将copy constructor分为trivial 和nontrivial两种:只有nontrivial的实例才会被合成于程序之中.决定一个copy constructor是 ...

  4. 构造函数语义学——Copy Constructor 的构造操作

    前言 在三种情况下,会以一个 object 的内容作为另一个 class object 的初值: object明确初始化 class X{...}; X x; X xx = x; object 被当作 ...

  5. 构造函数语义学——Copy Constructor 篇

    构造函数语义学--Copy Constructor 篇 本文主要介绍<深度探索 C++对象模型>之<构造函数语义学>中的 Copy Constructor 构造函数的调用时机 ...

  6. C++ 类 复制构造函数 The Copy Constructor

    一.复制构造函数的定义 复制构造函数是一种特殊的构造函数,具有一般构造函数的所有特性.复制构造函数创建一个新的对象,作为另一个对象的拷贝.复制构造函数只含有一个形参,而且其形参为本类对象的引用.复制构 ...

  7. 构造函数语义学——Default Constructor篇

    构造函数语义学--Default Constructor 篇 这一章原书主要分析了:编译器关于对象构造过程的干涉,即在对象构造这个过程中,编译器到底在背后做了什么 这一章的重点在于 default c ...

  8. 深度探索C++对象模型之第二章:构造函数语意学之Default constructor的构造操作

    C++新手一般由两个常见的误解: 如果任何class没有定义默认构造函数(default constructor),编译器就会合成一个来. 编译器合成的的default constructor会显示的 ...

  9. Copy Constructor的构造操作

    Copy Constructor的构造操作 有三种情况,会以一个object的内容作为另一个class object的初值: 1.  对一个object做显式的初始化操作 class X{…}; X ...

随机推荐

  1. 他们都没告诉你适配 Android N 需要注意什么

    还记得 6.0 对 Apache Http 库的废除导致的应用崩溃吗?还记得 6.0 中 MAC id 始终返回为空导致的唯一 id 混合生成算法大幅失效吗? 1. Android 中 Java 的实 ...

  2. 升级 node 版本

    npm install -g n n stablen v0.10.26 n 0.10.26

  3. 原创翻译:蓝牙(BLE)for iOS

    About Core Bluetooth 简要:核心蓝牙框架提供了iOS和MAC 应用程序与BLE 设备进行无线通信所需要的类.通过该框架,应用程序可以扫描.发现BLE 外设,如心率.电子温度传感器等 ...

  4. 10.4 noip模拟试题

    题目名称 PA 青春 三部曲 名称 huakai taritari truetears 输入 huakai.in taritari.in truetears.in 输出 huakai.out tari ...

  5. 动态拼接 sql的时候 里面 如果有变量的话 按上面的方式进行处理

    set @Sql_Sql = N' select top 1 @m_zw=zw,@m_zh=temp from ket where zd=''ddd'' ' print @Sql_Sql EXEC s ...

  6. Registry 类

    提供表示 Windows 注册表中的根项的 RegistryKey 对象,并提供访问项/值对的 static 方法. 继承层次结构 System.Object   Microsoft.Win32.Re ...

  7. 系统重装c盘后,mysql重新设置

    之前我的mysql装在d盘,重装了系统后,虽然只格式化了c盘,但mysql还是不能用了.我网上找了找.修改了一下配置. 1.首先设置环境变量,编辑path,在后面添加上mysql的安装路径 : 2.之 ...

  8. C# RSA加密/解密

    RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法, ...

  9. gSoap实现ONVIF中xsd__anyType到具体结构类型的转换

    上一篇文章已经粗略计划要讨论gsoap关于序列化/解析编程. 本文则阐述一下关于gsoap生成代码的一些重要特征方法及使用.如题,下我们从ONVIF生成的C码中,挑选简单的一个类型来试验一下与xsd_ ...

  10. C /CLI思辨录[阅读记录]

    C /CLI思辨录之拷贝构造函数(避免多个实例在相同的堆对象的错误处理) http://west263.com/info/html/chengxusheji/C-C--/20080224/9247.h ...