• C++ Primer 第十三章 拷贝控制


    当定义一个类时,我们显式或隐式指定在此类型的对象执行拷贝,移动,赋值,销毁时做什么,通过拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符和析构函数。

    拷贝赋值与销毁

    如果构造函数的第一个参数是自身类类型的引用,并且其他参数都有默认值,则此构造函数是拷贝构造函数。第一个参数一定是引用类型,并且一般为const类型。

    直接初始化对象时,我们使用最匹配参数的构造函数初始化对象,拷贝初始化时(赋值的形式)会使用拷贝构造函数初始化对象。通常拷贝初始化由拷贝构造函数来完成,但如果一个类有移动构造函数,则使用移动构造函数执行拷贝初始化。用等号(=)定义变量时,将一个对象作为实参传递给一个非引用类型的形参,从函数返回一个非引用类型的对象,用花括号初始化数组元素或聚合类中的成员时,这些情况会执行拷贝初始化。

    赋值运算符就是一个名为operator=的函数,赋值运算符返回一个指向其左侧运算对象的引用。如果未定义自己的拷贝赋值运算符,编译器会合成一个拷贝赋值运算符。

    析构函数与构造函数执行相反的操作,析构函数没有返回类型也不接受任何参数。析构函数不能重载,对于一个给定类,只能有一个析构函数。析构函数首先执行函数体,然后销毁成员,析构是隐式执行的,销毁内置指针类型的成员时不会delete所指向的对象。当指向一个对象的引用或指针离开作用域时,析构函数不会执行。

    如果一个类需要一个析构函数,几乎可以肯定该类也需要一个拷贝构造函数和拷贝赋值运算符。需要拷贝操作的类也需要拷贝赋值操作,需要拷贝赋值运算符的类也一定需要拷贝构造函数,但不一定需要析构函数。注意这里所说的需要是只自定义。

    可以通过将拷贝控制成员声明为=default来显示要求编译器生成合成的版本。

    通过在函数后面添加=delete来定义删除的函数,声明删除的函数将阻止对该函数的使用。析构函数不能是删除的,否则将无法销毁该对象,可以动态分配一个有删除的析构函数的对象,但是不能delete该对象。

    合成的拷贝控制成员可能是删除的,如果类的某个成员含有删除的拷贝控制成员或析构函数,则该类的合成拷贝控制也将是删除的。

    对于具有引用成员或const成员的类型,编译器不会为其合成构造函数,如果一个类有const成员,则不能使用合成的拷贝赋值运算符。对于有引用成员的类,合成拷贝赋值运算符被定义为删除的。本质上,当不能销毁拷贝赋值类的成员时,合成的拷贝控制成员就被定义为删除的。

    声明但不定义一个成员函数是合法的,访问一个未定义的成员将导致链接时错误。

    拷贝控制和资源管理

    通常管理类外资源的类需要定义拷贝控制成员。

    对于赋值运算符来说,即使将一个对象赋予它自身也应该能正常工作,好的方法是在销毁左侧运算对象之前拷贝右侧运算对象。赋值运算符组合了析构函数和拷贝构造函数的功能。

    交换操作

    如果一个类定义了自己的swap函数,算法将使用自定义函数,否则使用标准库swap版本。swap并不是必要的,但是使用了资源的类定义swap将是一种重要的优化手段。

    拷贝控制示例

  • 相关阅读:
    Windows OpenGL ES 图像反色
    OpenGL ES EGL eglCreatePbufferSurface
    OpenGL ES 名词解释(一)
    干货推荐!13 个技术电子书资源站,从此看书不求人
    awk输出单引号'的几种方式
    Ubuntu20.04 中文输入法失效问题解决
    在node中import from引入的文件要跟.js后缀,但是webapck不用?
    Promise 只处理失败的回调
    babel 转义,webpack压缩
    Promise 只处理成功回调
  • 原文地址:https://www.cnblogs.com/jefflee/p/6159992.html
Copyright © 2020-2023  润新知