Copy Constructor的构造操作

有三种情况,会以一个object的内容作为另一个class object的初值:

1、  对一个object做显式的初始化操作

class X{…};

X a;

X b = a;

2、当object被当做参数交给某个函数:

X a;

void foo(X x);

foo(a);

3、  当返回值为object:

X foo

{

X a;

return a;

}

假设class X显式定义了一个copy constructor,类似下面这样:

X::X(const X& x);

则在大部分情况下,当一个class object以另一个同类实例作为初值,上述的copy constructor就会被调用。

那如果class没有提供一个explicit copy constructor的话,编译器是如何处理的呢?这时就要所谓的default memberwise initialization起作用了。default memberwise initialization也就是把object内每一个内建的或派生的data member的值,拷贝到另一个object,对于member class object,则以递归的方式继续实施memberwise initialization。从对象的数据成员角度出发,具体到对象的每一个数据成员的操作,编译器通常采用(可以认为就是)bitwise copy(按位拷贝)操作,就像memcpy或者memset函数一样,原样将内存中的数据按位复制一份。但是并不是所有不提供explicit copy constructor的class都会展现bitwise copy。

像default constructor,C++ Standard把copy constructor区分为trivial和nontrivial两种。其中nontrivial copy constructor才会被编译器真正合成与程序之中,而trivial copy constructor实际上被没有被真正合成。决定copy constructor是否为trivial的标准对应的class是否展现出bitwise copy。

那什么情况下,copy constructor是nontrivial,或者说class不展现bitwise copy呢?分为以下4中情况:

第一、当class内含有一个member object,而后者的class有一个copy constructor(无论是显式声明,还是编译器隐式合成)。

       因为编译器必须将member object的“copy constructor的调用操作”安插到被编译器合成的copy constructor中,否则无法调用member object的copy constructor。

第二、当class继承自一个base class,而后者存在一个copy constructor(无论是显式声明,还是编译器隐式合成)。

       因为编译器必须将base class的“copy constructor的调用操作”安插到被编译器合成的copy constructor中,否则无法调用base class的copy constructor。

第三、当class声明了至少一个virtual function

当class至少有一个virtual function时,这个class的object必然会有virtual table和virtual point。所以对于每一个新产生的class object的virtual point,必须正确设定初值。如果采用bitwise copy,在一般情况下是可以满足要求的。但是当一个base class object以其derived class的object内容做初始化时,如果采用bitwise copy的话,virtual point就难以保证安全,因为从derived class object拷贝过来的virtual point指向的还是derived class的virtual table,而并不是base class的virtual table。

第四、当class直接或间接地继承了至少一个virtual base class

       每一个编译器对于虚拟继承的支持承诺,都代表必须让derived class object中的virtual base class subobject位置在执行期就准备妥当。但bitwise copy 可能会破坏这个位置,所以编译器在这种情况不会采用bitwise copy。

总结,以上4种情况下class不再保持bitwise copy,而且explicit copy constructor未被声明,编译器为了正确处理“以一个class object作为另一个class object的初值”,会为class合成nontrivial copy constructor。

 

Copy Constructor的构造操作的更多相关文章

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

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

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

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

  3. Default Constructor的构造操作

    Default Constructor的构造操作 C++ Annotated Reference Manual书中的Section 12.1说过:default constructor 只有在编译器需 ...

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

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

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

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

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

    一.Copy Constructor的构建操作 就像 default constructor 一样,如果class没有申明一个 copy constructor,就会隐含的声明或隐含的定义一个.生成的 ...

  7. C++-copy constructor、copy-assignment operator、destructor

    本文由@呆代待殆原创,转载请注明出处. 对于一个类来说,我们把copy constructor.copy-assignment operator.move constructor.move-assig ...

  8. C++对象模型——Default Constructor的建构操作(第二章)

    第2章    构造函数语意学 (The Semantics of Constructor) 关于C++,最常听到的一个抱怨就是,编译器背着程序猿做了太多事情.Conversion运算符就是最常被引用的 ...

  9. copy constructor

    copy constructor也分为trivial和nontrivial两种 如果class展现出bitwise copy semantics(按位拷贝语义),则不会构造出 copy constru ...

随机推荐

  1. logger日志工具类

    日志工厂类 package cn.itcast.utils; import java.util.logging.FileHandler; import java.util.logging.Handle ...

  2. 转:jquery的live和on

    参考1,参考2 给元素绑定事件,本人用的jquery版本大多为1.7和1.8的,所以一直习惯于用live(),但是最近朋友突然问我,怎么给新生成的dom元素绑定事件,我随口回答live(),结果他给我 ...

  3. 解决maven web项目Cannot detect Web Project version. Please specify version of Web Project through...的错误

    前面已经创建maven web工程,但是问题来了,创建maven web工程之后会出现如下的错误,在pom.xml文件头部 有以下的错误 Description Resource Path Locat ...

  4. Spring 配置文件XML -- <beans>中属性概述

    beans : xml文件的根节点. xmlns : XML NameSpace的缩写,因为XML文件的标签名称都是自定义的,自己写的和其他人定义的标签很有可能会重复命名,而功能却不一样,所以需要加上 ...

  5. curl 使用

    1.cURL介绍 cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 cURL 库.本文将介绍 cURL 的一些高级特性 ...

  6. datatables.js 里面遇到的问题

    1. 假如需要A行的data 和 B行的data 合并 在B行 data:name 在A行的 render:function(){ return data+full.name   此时返回的就是A+B ...

  7. nodejs在cmd提示不是内部或外部命令解决方法

    今天用cmd安装个库,结果发现node不是内部命令,于是搜索了下解决方法,发现原来我上次重装nodejs换了个安装位置,path环境变量忘改了. 找到变量值中node的安装地址,比如C:develop ...

  8. python学习day2

    一.模块初识 python模块 模块让你能够有逻辑地组织你的Python代码段. 把相关的代码分配到一个 模块里能让你的代码更好用,更易懂. 模块也是Python对象,具有随机的名字属性用来绑定或引用 ...

  9. .net 中HttpClient 携带cookie传输

    CookieContainer cookieContainer = new CookieContainer(); Cookie cookie = new Cookie("username&q ...

  10. Snacks

    Snacks 题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5692 dfs序+线段树 这道题涉及到对整棵树的值修改,考虑将树状结构用dfs ...