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

对于一个类来说,我们把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。

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

何时发生copy constructor调用

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

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

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

1 std::string s1("balabala");                       //direct initialization
2 std::string s2(10, ‘a‘);                          //direct initialization
3 std::string s3 = s2;                              //copy initialization
4 std::string s4 = std::string(s3);                 //copy initialization
5 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的行为更像内置类型而决定的。

1 class Foo{
2 public:
3     Foo& operator=(const Foo&);
4     //...
5 };

何时发生copy-assignment operator调用

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

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

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

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

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

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

 Destructor

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

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

1 class Foo{
2 public:
3     ~Foo();
4     //...
5 };

何时发生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可以写在方法声明的地方也可以写在方法定义的地方。

1 class Foo{
2 public:
3     Foo() = default;                     //显式说明使用默认版本
4     Foo(const Foo&) = delete;            //delete copy constructor
5     Foo& operator=(const Foo&) = delete; //delete copy-assignment operator
6     ~Foo() = default;                    //显式说明使用默认版本
7     void myFuntion() = delete;           //delete自己的方法
8     //...
9 };
时间: 2024-10-05 00:04:03

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

类的三个特殊成员Copy Constructor、Copy-Assignment Operator、Destructor重载与使用

今天看<C++ Primer>的13.1节--Copy, Assign, and Destroy 被这几个玩意儿弄得晕得不行: ◆   Copy Constructor ◆   The Copy-Assignment Operator ◆   Destructor 主要问题集中在: ◆   我们在什么时候需要自己重写? ◆   系统会在什么时候用我们重写的版本? ◆   拷贝构造和赋值操作符的区分到底是什么? 0x00 特性 为了区分他们,我们首先要分别从每一个的特性说起 这个可以参考 htt

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

2.2    Copy Constructor 的建构操作 有三种情况,会以一个object的内容作为另一个 class object的初值,最明显的一种情况就是对一个object做显式的初始化操作,例如: class X { ... }; X x; // 明确地以一个object的内容作为另一个class object的初值 X xx = x; 另两种情况是当object被当作参数交给某个函数时,例如 extern void foo(X x); void bar() { X xx; // 以x

深入探索c++对象模型-&gt;2.2 Copy Constructor的构造操作

一.只有当class不展现出bitwise copy semanties时,编译器才会为class生成copy constructor.那么当什么时候回出现非bitwise copy呢? 1.当class内含一个member object而后者的class声明有一个copy constructor时(不论是显示声明或是被合成得到的): 2.当class继承自一个base class而后者存在一个copy constructor时. 3.当class声明了一个或多个virtual function

C++中关于继承中constructor、copy constructor、copy assignment的一些笔记

1.如果成员初值列不包含基类,则constructor.copy constructor  都隐式的调用基类无参的constructor 2.派生类默认的copy constructor.copy assignment会调用基类的  相应成员.而自己定义的则不会. 3.如果基类的copy assignment为private,则派生类不会生成默认的  copy assignment

c++笔记:const、初始化、copy构造/析构/赋值函数

构造函数 Default构造函数:可被调用而不带任何实参的构造函数,没有参数或每个参数都有缺省值.如: class A { public: A(); }; 将构造函数声明为explicit,可阻止它们被用来执行隐式类型转换,但仍可用来进行显示类型转换.如: class B { public: explicit B(int x = 0, bool b = ture); }; copy构造函数:用于以同型对象初始化自我对象,以passed by value的方式传递对象:· copy assignm

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

如下为类型CMyString的声明,请为该类型编写构造函数.copy构造函数.析构函数和赋值运算符函数. 1 class CMyString 2 { 3 public: 4 CMyString(const char* pData = nullptr); 5 CMyString(const CMyString& str); 6 ~CMyString(void); 7 8 CMyString& operator = (const CMyString& str); 9 10 void P

iOS-assign、copy 、retain等关键字的含义

iOS中assign.copy .retain等关键字的含义 assign: 简单赋值,不更改索引计数 copy: 建立一个索引计数为1的对象,然后释放旧对象 retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 Copy其实是建立了一个相同的对象,而retain不是: 比如一个NSString对象,地址为0×1111,内容为@”STR” Copy到另外一个NSString之 后,地址为0×2222,内容相同,新的对象retain为1, 旧有对象没有变化 retai

iOS开发-assign、retain、copy、strong、weak的区别

对于初学的开发者,对于assign.retain.copy.strong.weak的用法及意义可能不是很明白,我对于这个问题也研究了很久,写篇博文,巧巧代码,让我们来瞧瞧吧! 先定义一个Student类: #import <Foundation/Foundation.h> @interface Student : NSObject @property (nonatomic, copy) NSString *name; @end 然后先是mrc下的assign声明 @property (nona

OC语法——Object-C retain、copy、mutableCopy的详细分析

OC语法中的retain.copy.mutableCopy 大家都基本知道它的基本意思,但是对于mutable类型和immutable类型的处理上有很多童鞋并没有真正测试过,今天就和大家分享下: 1.先来看下immutable类型的非容器类: NSString的retain.copy和mutableCopy的测试 NSString *string = @"abc"; NSString *retainString = [string retain]; NSString *copyStri