Copy Constructor的构造操作
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的构造操作的更多相关文章
- 构造函数语义学——Copy Constructor 的构造操作
前言 在三种情况下,会以一个 object 的内容作为另一个 class object 的初值: object明确初始化 class X{...}; X x; X xx = x; object 被当作 ...
- 深度探索C++对象模型之第二章:构造函数语意学之Copy constructor的构造操作
C++ Standard将copy constructor分为trivial 和nontrivial两种:只有nontrivial的实例才会被合成于程序之中.决定一个copy constructor是 ...
- Default Constructor的构造操作
Default Constructor的构造操作 C++ Annotated Reference Manual书中的Section 12.1说过:default constructor 只有在编译器需 ...
- 深度探索C++对象模型之第二章:构造函数语意学之Default constructor的构造操作
C++新手一般由两个常见的误解: 如果任何class没有定义默认构造函数(default constructor),编译器就会合成一个来. 编译器合成的的default constructor会显示的 ...
- 构造函数语义学之Copy Constructor构建操作(2)
二.详述条件 3 和 4 那么好,我又要问大家了,条件1 和 2比较容易理解.因为member object或 base class 含有copy constructor.那么member objec ...
- 构造函数语义学之Copy Constructor构建操作(1)
一.Copy Constructor的构建操作 就像 default constructor 一样,如果class没有申明一个 copy constructor,就会隐含的声明或隐含的定义一个.生成的 ...
- C++-copy constructor、copy-assignment operator、destructor
本文由@呆代待殆原创,转载请注明出处. 对于一个类来说,我们把copy constructor.copy-assignment operator.move constructor.move-assig ...
- C++对象模型——Default Constructor的建构操作(第二章)
第2章 构造函数语意学 (The Semantics of Constructor) 关于C++,最常听到的一个抱怨就是,编译器背着程序猿做了太多事情.Conversion运算符就是最常被引用的 ...
- copy constructor
copy constructor也分为trivial和nontrivial两种 如果class展现出bitwise copy semantics(按位拷贝语义),则不会构造出 copy constru ...
随机推荐
- redis cluster中添加删除重分配节点例子
redis cluster配置好,并运行一段时间后,我们想添加节点,或者删除节点,该怎么办呢. 一,redis cluster命令行 //集群(cluster) CLUSTER INFO 打 ...
- mac xcode 快捷键
shift + cmd + n 新建项目 cmd + n 新建文件 视图 option + cmd + 回车 打开助理编辑器 cmd + 回车 显示 ...
- 【小技巧】C#判断电脑是否联网
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- apache 修改连接数(转)
1.先要修改最大连接数,必须了解Apache的MPM(Multi -Processing Modules,多道处理模块)Apache2.0中MPM分为3种(perfork.worker.event). ...
- java 基础知识2
- 自定义按钮~自适应布局~常见bug
一.元件 自定义按钮可用button或a display为 inline-block 方便设置格式,通过 padding,height,line-height,font-size设置按钮的大小 & ...
- 2、变量var关键字
我们在看js声明变量的时候,经常会发现有的变量前会带var 但又的则没有,那么这究竟有什么区别呢? 如果这种情况发生在函数里的话, 加var定义的变量是局部变量,不加var定义的就成了全局变量. // ...
- 布局常见问题之css实现多行文本溢出显示省略号(…)全攻略
省略号在ie中可以使用text-overflow:ellipsis了,但有很多的浏览器都需要固定宽度了,同时ff这些浏览器并不支持text-overflow:ellipsis设置了,下文来给各位整理一 ...
- UITableView控制头部View
首先我们先集成一个UIView做一个自己的View #import <UIKit/UIKit.h> @interface MyView : UIView @property (nonato ...
- 安卓---下拉刷新---上拉加载---解决导入library等自生成库文件失败的问题
本文的下拉刷新以及上拉加载都是用PullToRefresh实现的,关于PullToRefresh的介绍以及源码,网上可以找到很多,本人在此不再赘述. PullToRefresh是一套实现非常好的下拉刷 ...