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. foreach绑定

    目的 foreach可以将一个数组中的实体循环的进行绑定.这在将一个list显示成table时非常有用. 假设数组是observable的,当在绑定后做了add, remove,或者重新排序后,绑定会 ...

  2. 我的学习记录JAVA第二天

  3. 找出Java数组中不同的值

    public void deltp(PrintWriter out) { try{ PageData pd = new PageData(); pd = this.getPageData(); Str ...

  4. MySQL的保留关键字,使用时尽量避免

    今天用phpmyadmin时,注意到一个提示: 列名 'update' 是一个MySQL 保留关键字. 突然意识到还是应该尽量避免这些保留关键字,也百度了一下.找到了这些关键字,列出来下 使用mysq ...

  5. CMake如何执行shell命令

    我在cmake编译后想执行一些特定的shell命令(执行.lcov收集代码覆盖报告等),我又不想写到XX.sh的shell脚本中,如何直接通过CMake执行shell命令呢? 在网上翻江倒海了一下,找 ...

  6. C#使用LitJson解析JSON(转)

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standard ECMA-262 3rd Edition - Decembe ...

  7. Hdu 3363 Ice-sugar Gourd(对称,圆)

    Ice-sugar Gourd Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  8. 精简CSS

    1.简化你的注释 2.简化颜色代码 3.使用单行属性代替多行属性 4.值为0时可省略单位 5.同时设置多个元素的属性用分组形式 6.删除空白和换行 7.设定过期时间

  9. Vue.js + Seajs 实例(包含vue-router使用)

    这个Demo 相关JS: Sea.js : Version 2.3.0 seajs-text :  Version 2.3.0 vue.js : Version 1.0.24 vue-router: ...

  10. NYIST OJ 题目38 布线问题

    最小生成树水题,先按最小生成树做,答案最后加上最小的从第i号楼接线到外界供电设施所需要的费用即可. #include<cstdio> #include<cstring> #in ...