一、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. Java基础知识强化之集合框架笔记27:ArrayList集合练习之去除ArrayList集合中的重复字符串元素

    1. 去除ArrayList集合中的重复字符串元素(字符串内容相同) 分析: (1)创建集合对象 (2)添加多个字符串元素(包含重复的) (3)创建新的集合 (4)遍历旧集合,获取得到每一个元素 (5 ...

  2. 数据结构 : Hash Table

    http://www.cnblogs.com/lucifer1982/archive/2008/06/18/1224319.html 作者:Angel Lucifer 引子 这篇仍然不讲并行/并发. ...

  3. MySQL日志概述

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3859866.html ...

  4. C++链表与键值对

    <算法>一书中,在算法3.1中提到了Map的实现,这里根据书上的思想,用单向链表简单写了写. #ifndef SEQUENTIAL_H #define SEQUENTIAL_H templ ...

  5. rabbitmq 消息持久化

    rabbitmq 消息持久化 2016-02-18 11:19 224人阅读 评论(0) 收藏 举报  分类: 综合(15)  版权声明:本文为博主原创文章,未经博主允许不得转载. 二: 任务分发 & ...

  6. Android之提交数据到服务端方法简单封装

    在Android应用中,除了单机版的应用,其余的应用免不了需要频繁地与服务端进行数据交互,如果每一种方法都独立写一段代码,那会造成代码大量重复,冗余,这不是我们所希望的,所以我们可以对其进行一些封装, ...

  7. ajax xmlhttp下open方法POST、GET参数的区别

    1. get是从服务器上获取数据(会暴露客户端ip),post是向服务器传送数据.2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看 ...

  8. PL/SQL Developer远程连接Oracle数据库

    首先打开电脑,到pl/sql安装的指定目录[D:\app\DZL\product\11.2.0\dbhome_1\NETWORK\ADMIN]找到[tnsnames.ora]     打开[tnsna ...

  9. 使用Xcode插件,让iOS开发更加便捷

    在iOS开发过程中,写注释是一项必不可少的工作.这不仅有助于自己对代码整理回顾,而且提高了代码的可读性,让代码维护变得容易.但是,写注释又是一项枯燥的工作.我们浪费了大量的时间在输入/*,*,*/这样 ...

  10. ios8及以前的特性

    目前最新系统为ios8.以下为历代系统的回顾: iOS 1 关键词:iPhone的诞生 也许放在现在来看,当时的情景很难想象.当第一代iPhone正式发布时,在某些功能和方面其实是要远远落后于当时的竞 ...