美文网首页
(二十)C++篇-自定义类(五)-复制构造函数

(二十)C++篇-自定义类(五)-复制构造函数

作者: GoodTekken | 来源:发表于2022-07-05 14:32 被阅读0次

复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。

析构函数是构造函数的互补:当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放对象时构造或在对象的生命期中所获取的资源。不管类是否定义了自己的析构函数,编译器都自动执行类中非static 数据成员的析构函数。

复制构造函数、赋值操作符和析构函数总称为复制控制。编译器自动实现这些操作,但类也可以定义自己的版本。

通常,编译器合成的复制控制函数是非常精练的——它们只做必需的工作。但对某些类而言, 依赖于默认定义会导致灾难。 实现复制控制操作最困难的部分,往往在于识别何时需要覆盖默认版本。 有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员。

复制构造函数
只有单个形参,而且该形参是对本类类型对象的引用(常用 const 修饰),这样的构造函数称为复制构造函数。与默认构造函数一样,复制构造函数可由编译器隐式调用。复制构造函数可用于:
• 根据另一个同类型的对象显式或隐式初始化一个对象。
• 复制一个对象,将它作为实参传给一个函数。
• 从函数返回时复制一个对象。
• 初始化顺序容器中的元素。
• 根据元素初始化式列表初始化数组元素。

禁止复制
为了防止复制,类必须显式声明其复制构造函数为 private

如果复制构造函数是私有的,将不允许用户代码复制该类类型的对象,编译器将拒绝任何进行复制的尝试。
然而,类的友元和成员仍可以进行复制。如果想要连友元和成员中的复制也禁止,就可以声明一个(private)复制构造函数但不对其定义。

赋值操作符
重载操作符是一些函数,其名字为 operator 后跟着所定义的操作符的符号。因此,通过定义名为 operator= 的函数,我们可以对赋值进行定义。像任何其他函数一样,操作符函数有一个返回值和一个形参表。形参表必须具有与该操作符数目相同的形参(如果操作符是一个类成员,则包括隐式 this 形参)。赋值是二元运算,所以该操作符函数有两个形参:第一个形参对应着左操作数,第二个形参对应右操作数。
大多数操作符可以定义为成员函数或非成员函数。当操作符为成员函数时,它的第一个操作数隐式绑定到 this 指针。有些操作符(包括赋值操作符)必须是定义自己的类的成员。因为赋值必须是类的成员,所以 this 绑定到指向左操作数的指针。因此,赋值操作符接受单个形参,且该形参是同一类类型的对象。右操作数一般作为 const 引用传递。

一般而言,如果类需要复制构造函数,它也会需要赋值操作符。
实际上,就将这两个操作符看作一个单元。如果需要其中一个,我们几乎也肯定需要另一个。

析构函数
构造函数的一个用途是自动获取资源。例如,构造函数可以分配一个缓冲区或打开一个文件,在构造函数中分配了资源之后,需要一个对应操作自动回收或释放资源。析构函数就是这样的一个特殊函数,它可以完成所需的资源回收,作为类构造函数的补充。

动态分配的对象只有在指向该对象的指针被删除时才撤销。如果没有删除指向动态对象的指针,则不会运行该对象的析构函数,对象就一直存在,从而导致内存泄漏,而且,对象内部使用的任何资源也不会释放。

当对象的引用或指针超出作用域时,不会运行析构函数。只有删除指向动态分配对象的指针或实际对象(而不是对象的引用)超出作用域时,才会运行析构函数。

何时编写显式析构函数
许多类不需要显式析构函数,尤其是具有构造函数的类不一定需要定义自己的析构函数。仅在有些工作需要析构函数完成时,才需要析构函数。析构函数通常用于释放在构造函数或在对象生命期内获取的资源

如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是一个有用的经验法则。这个规则常称为三法则,指的是如果需要析构函数,则需要所有这三个复制控制成员。

测试代码如下:

#include <vector>
#include <iostream>

struct Exmp1
{
    //默认构造函数
    Exmp1(){std::cout<<"Exmp1()"<<std::endl;}
    
    //复制构造函数
    Exmp1(const Exmp1&)
    {std::cout<<"Exmp1(const Exmp1&)"<<std::endl;}
    
    //赋值操作符
    Exmp1& operator = (const Exmp1&abc)
    {
        std::cout<<"Operator:(const Exmp1&)"<<std::endl;
        return *this;
    }
    
    //析构函数
    ~Exmp1(){std::cout<<"~Exmp1()"<<std::endl;}
};

void func1(Exmp1 obj)  //形参为Exmp1对象
{
}

void func2(Exmp1& obj)  //形参为Exmp1对象的引用
{
}

Exmp1 func3()
{
    Exmp1 obj;
    return obj;  //返回Exmp1对象
}

int main()
{
    Exmp1 eobj;  //调用默认构造函数创建Exmp1对象eobj
    func1(eobj); //调用复制构造函数
            //将形参Exmp1对象创建为实参Exmp1对象的副本
            //函数执行完毕后调用析构函数撤销形参Exmp1对象
    func2(eobj);  //形参为Exmp1对象的引用,无需调用复制构造函数传递实参
    
    eobj = func3();//调用默认构造函数创建局部Exmp1对象
            //函数返回时调用复制构造函数创建作为返回值副本的Exmp1对象
            //然后调用析构函数撤销局部Exmp1对象
            //然后调用赋值操作符
            //执行完赋值操作符
            //调用析构函数撤销作为返回值副本的Exmp1对象
            
    Exmp1 *p = new Exmp1;//调用默认构造函数动态创建Exmp1对象
    std::vector<Exmp1> evec(3);//调用3次默认构造函数
            //然后调用3次析构函数撤销局部Exmp1对象
    delete p;//调用析构函数撤销动态创建的Exmp1对象
    return 0;
}

测试结果:

tekken@tekken:~/C++WS$ ./a.out 
Exmp1()
Exmp1(const Exmp1&)
~Exmp1()
Exmp1()
Operator:(const Exmp1&)
~Exmp1()
Exmp1()
Exmp1()
Exmp1()
Exmp1()
~Exmp1()
~Exmp1()
~Exmp1()
~Exmp1()
~Exmp1()

相关文章

  • (二十)C++篇-自定义类(五)-复制构造函数

    复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象...

  • C++ 构造函数的奇葩问题(A篇)

    前文:C++ 面向对象-类接口和类的实现 带参数的构造函数 承接上文,这里先说带参数的构造函数,自定义的构造函数必...

  • [剑指offer]01-赋值运算符函数

    在面向对象C++语言中,用户定义一个类时,会默认生成四个成员函数:默认构造函数、默认析构函数、默认复制构造函数和默...

  • [初学C++]构造和析构函数

    什么是构造函数定义C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数.C++对类提...

  • C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制

    在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋...

  • C++ 构造函数,类的成员变量

    c++ 05 构造函数无参构造函数有参构造函数 拷贝构造函数 浅拷贝 深拷贝 类的成员变量 四类特殊的成员变量

  • C++:面向对象基础

    构造函数 C++中有三种构造函数:默认构造函数,有参构造函数,拷贝构造函数 类对象的初始化 括号法//默认构造函数...

  • c++复制构造函数

    基本概念 复制构造函数(Copy constructor)是c++中的一个特殊构造函数,也称拷贝构造函数,它只有一...

  • C++ 构造过程

    构造函数 C++中每个类必须有一个构造函数,如果用户没有自行编写构造函数,则C++会自动提供一个无参数的构造函数,...

  • 1.2.04_C++ 类构造函数 & 析构函数

    C++ 类 & 对象 类的构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。 构造函...

网友评论

      本文标题:(二十)C++篇-自定义类(五)-复制构造函数

      本文链接:https://www.haomeiwen.com/subject/qrssbrtx.html