本文由@呆代待殆原创,转载请注明出处。

对于一个类来说,我们把copy constructor、copy-assignment operator、move constructor、move-assignment operator、destructor统称为copy control。

今天我们先来聊聊其中的copy constructor、copy-assignment operator的destructor这三个。

copy constructor

copy constructor:一个constructor如果他的第一个参数是对类的引用,且其他的参数都有缺省值(default values)则,这是一个copy constructor。

1,第一个参数必须是引用类型,因为当我们把一个object当做参数传递给一个方法的非引用变量的时候会自动调用copy constructor方法,如果copy constructor自身的参数就是非引用类型的话,这个方法就会引起无限递归调用,然后你的程序就boomshakalaka~~。

2,一般我们会把第一个参数设成const,因为一般情况下不会对其进行修改,除非你另有打算。

3,因为copy constructor在很多情况下是默认调用的,如以下情况,所以一般不会把copy constructor设成explicit。

 std::string s;
std::string s1 = s; //隐式调用了copy constructor
std::string s2 = std::string(s1);//显式调用了copy constructor
 class Foo{
public:
Foo(const Foo&);
//...
};

何时发生copy constructor调用

为了弄清这个问题我们需要弄清另外一组概念:direct initialization 和copy initialization。

direct initialization:要求编译器按照一般的方法匹配(function matching)来选择要调用的方法。

copy initialization:要求编译器将右操作数拷贝到左操作数,有必要的话还会进行类型转换,这个过程会调用copy constructor或者move constructor(本文暂不介绍)。

 std::string s1("balabala");                       //direct initialization
std::string s2(, 'a'); //direct initialization
std::string s3 = s2; //copy initialization
std::string s4 = std::string(s3); //copy initialization
std::string s5 = "const char* converts to string";//copy initialization

copy initialization发生的情况如下:

1,用=来初始化定义的变量时。

2,把一个object当做参数传递给一个方法的非引用变量的时。

3,方法返回一个非引用类型的object时。(返回时会首先生成一个临时object)

4,用花括号列表初始化一个数组或聚合类(aggregate class)成员时。

由于编译器带来的误解:

现在的编译器有时候会自动绕过copy constructor即编译器会把下面这一句话

std::Book book = "9-9-9-9";//假设Book是一个自定义的类

换成下面这个

std::Book book("9-9-9-9");

请注意在执行上上面两句语言是完全不一样的,第一句会首先调用Book(const char*)构造函数生成一个临时object然后再调用Book(const Book&)把临时object复制给book。而第二句话会直接调用Book(const char*)然后完事儿。如果你想验证他们的区别可以实现Book类并将Book(const Book&)设置成私有方法(防止编译器自动优化),之后你就会发现第一条语句无法执行了。

Copy-assignment operator

copy-assignment operator:写这个方法就是对=操作符进行重载。

1,copy-assignment operator的返回值一般是对其左操作数(left-hand operand)的引用,这是为了让object的行为更像内置类型而决定的。

 class Foo{
public:
Foo& operator=(const Foo&);
//...
};

何时发生copy-assignment operator调用

答案很显然是用到=操作符的时候啊,但是这里要注意的是

初始化的时候并不会调用copy-assignment operator

初始化的时候并不会调用copy-assignment operator

初始化的时候并不会调用copy-assignment operator

重要的事情说三遍,举例如下

 std::string s;
std::string s1 = s; //对s1进行初始化,调用的是copy constructor
s1 = s; //对s1进行赋值,调用的是copy-assignment operator

 Destructor

Destructor:destructor有两个部分,function body和destruction part,前者由类的编写者写明需要做的内容,后者是隐式的,不需要程序员关心,在function body执行完后自动执行,会销毁类的非静态数据成员。

1,因为Destructor没有参数,所以它是不能被重载的

 class Foo{
public:
~Foo();
//...
};

何时发生Destructor调用

1,当超出object 的作用域(scope)时。

2,容器销毁时(container),里面的元素(element)也会跟着调用自身的destructor从而销毁。

3,人为使用delete的时候。

4,由某个表达式创建的临时变量在这个表达式执行完后将自动调用destructor从而销毁。

5,类的成员如果自身有destructor,会在这个类销毁的时候调用自身的destructor。

 关于编译器自动提供的版本(Synthesized)

Synthesized copy constructor:即使我们提供了其他版本的copy constructor,编译器仍然会提供这个版本的copy constructor给我们,它会依次复制非静态成员给被创建的object,对数组也能正常工作,对于class类型会调用它们自己的copy constructor。

Synthesized copy-assignment operator:行为和Synthesized copy constructor类似,依次把非静态成员复制给左操作数。

Synthesized destructor:destructor的function body为空。

 关于何时我们需要自定义上述的三个方法

1,当需要destructor时,上述三给方法都是需要的。

2,当需要copy constructor时,copy-assignment operator也是需要的,反之亦然。

而当我们需要删除自己动态分配的内存时,就要用到destructor。

当我们需要进行深度复制时会用到另外两个,比如对指针指向的元素进行复制等等。

关于delete和default的用法

我们可以用default显示声明我们想要用默认版本的copy control,也可以用delete显示声明我们完全不需要这类方法来达到禁止这个object进行相关的复制和赋值操作。

1,我们能delete除了destructor以外的所有方法来达到显示告知这个object不能进行相关操作的目的,delete只能写在一次声明出现的地方。

2,我们能对所有有默认版本的函数用default显示声明我们需要这个默认版本,default可以写在方法声明的地方也可以写在方法定义的地方。

 class Foo{
public:
Foo() = default; //显式说明使用默认版本
Foo(const Foo&) = delete; //delete copy constructor
Foo& operator=(const Foo&) = delete; //delete copy-assignment operator
~Foo() = default; //显式说明使用默认版本
void myFuntion() = delete; //delete自己的方法
//...
};

参考资料:《C++ primer 英文第五版》

C++-copy constructor、copy-assignment operator、destructor的更多相关文章

  1. Effective C++ 第0章 copy constructor和copy assignment operator

    拷贝构造函数(copy constructor)被用来以一个对象来初始化同类型的另一个对象,拷贝赋值运算符(copy assignment operator)被用来将一个对象中的值拷贝到同类型的另一个 ...

  2. copy constructor和copy assignment operator的区别

    拷贝构造函数(copy constructor)被用来以一个对象来初始化同类型的另一个对象,拷贝赋值运算符(copy assignment operator)被用来将一个对象中的值拷贝到同类型的另一个 ...

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

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

  4. Copy constructor vs assignment operator in C++

    Difficulty Level: Rookie Consider the following C++ program. 1 #include<iostream> 2 #include&l ...

  5. C++异常安全、copy and swap

    异常安全的代码是指,满足两个条件 1异常中立性 : 是指当你的代码(包括你调用的代码)引发异常时,这个异常 能保持原样传递到外层调用代码.(异常中立,就是指任何底层的异常都会抛出到上层,也就相当于是异 ...

  6. 请为CMyString类型编写构造函数、copy构造函数、析构函数和赋值运算符函数。

    如下为类型CMyString的声明,请为该类型编写构造函数.copy构造函数.析构函数和赋值运算符函数. class CMyString { public: CMyString(const char* ...

  7. 【iOS atomic、nonatomic、assign、copy、retain、weak、strong】的定义和区别详解

    一.atomic与nonatomic 1.相同点 都是为对象添加get和set方法 2.不同点 atomic为get方法加了一把安全锁(及原子锁),使得方法get线程安全,执行效率慢 nonatomi ...

  8. iOS中assign、copy 、retain等关键字的含义

    iOS中assign.copy .retain等关键字的含义  转自:http://my.oschina.net/majiage/blog/267409 assign: 简单赋值,不更改索引计数cop ...

  9. Objective-C中的Strong、Copy与MutableCopy

    面试过程中经常被问到ARC中Strong.Copy的区别是什么.普通的回答是:一样.文艺(正确)的回答是:分情况(我擦!WQY#$&Y**%OWEUR) 可以先参考这篇文章http://www ...

随机推荐

  1. 常见的mongo shell命令

    启动mongo shell 在windows下,双击mongo.exe可以启动mongo shell 查询库.表及选择库 查询所有库命令: show dbs 应用某一个db use jxs_datab ...

  2. 用keyword实现Editor.GetSelection的退出功能

    有时候我们在使用 GetSelection 功能让用户选择实体时,可能会给用户提供一些 keyword 选项,要接收用户选择的 keyword 选项,需要用到 PromptSelectionOptio ...

  3. AJAX制作JSON格式的实时更新数据的方法

    之前有写过这样的文章,但是出现了几个问题,第一,如果每秒都像数据库发送请求势必会造成服务器的压力过大,第二,如果使用JS的话,是不可以取得系统时间的,因为JS运行在客户端,所以只能取得客户端时间, 如 ...

  4. CCF 201312-3 最大的矩形 (暴力,离散化)

    问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是hi.这n个矩形构成了一个直方图.例如,下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3 ...

  5. button 禁止

    1.按钮的id为btnzhuce==> 控制按钮为禁用:  $("#btnzhuce").attr({"disabled":"disabled& ...

  6. 自定义滚动控件(Pagecontrol)

    // // MyPageCorol.h // lejiahui // // Created by iOS开发 on 16/4/10. // Copyright © 2016年 zhongmingwuy ...

  7. Firefox常用插件

    一.Web浏览使用插件 1.Adblock Plus广告拦截插件:能够自动拦截很多弹出广告,同时支持右键拦截指定信息 2.惠惠购物助手支持各大购物网站商品实时价格比较,非常棒的网站购物利器,插件下载地 ...

  8. mongo常用命令

    1.由于mongo没有关系型数据库常用,一些基础的命令容易忘记 db.table.update( { "_id" : xxx } , { $set : { "field1 ...

  9. android Intent的startActivityForResult()方法

    startActivityForResult() 之前学习了利用Intent跳转页面的同时传值,但有的时候需要从跳转到的页面返回所需要的值(如修改了用户信息,需要返回修改的信息),通俗的意思就是A.A ...

  10. javascript js 内存泄露工具使用

    javascript内存泄露工具使用 原文:http://lanhy2000.blog.163.com/blog/static/43678608201121472644851/ 2011-03-14 ...