C++拷贝构造函数和运算符重载--1

简介: C++拷贝构造函数和运算符重载--1

一,拷贝构造函数

概念:在类的定义中,构造函数只是单纯将内置类型进行初始化,而拷贝构造函数是将整个类进行拷贝到另一个类中进行初始化。在定义拷贝构造函数时,只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。


这里要说明的是,拷贝构造函数也是特殊的成员函数,其特征如下:


       1,拷贝构造函数是构造函数的一个重载形式。


       2,拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为形参相当于实参的临时拷贝,在拷贝中会触发另一个拷贝构造函数的调用,从而引发无穷递归调用。传引用的话只会将源对象的别名进行拷贝,不会进行整体拷贝,从而避免了这种问题。


class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    //Date(const Date d)// 错误写法: 编译报错,会引发无穷递归
    Date(const Date& d)// 正确写法
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1;//调用构造函数
    Date d2(d1);//用类进行初始化,会调用拷贝构造函数
    return 0;
}

fd670ddcac764bb4b6b19a86f62256bc.png

引发无穷递归的过程图




       3,若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数只会进行浅拷贝,或者值拷贝。(浅拷贝是指只拷贝对象的基本数据类型和引用地址,不会拷贝引用地址所指向的对象,即原对象中的数据所指向的空间将与拷贝后的对象的数据所指向的空间相同)。


       这里要说明的是默认拷贝构造函数的处理对象不跟默认构造函数一样,但处理自定义类型的方式跟默认构造函数一样。默认拷贝构造函数会对自定义类型和内置类型都做处理,其中,内置类型成员完成浅拷贝,自定义类型成员将会调用这个成员的拷贝构造。


#include <iostream>
using namespace std;
class Time
{
public:
    Time() {
        _hour = 1;
        _minute = 1;
        _second = 1;
    }
    Time(const Time& t) {
        _hour = t._hour;
        _minute = t._minute;
        _second = t._second;
        cout << "Time对象的拷贝构造" << endl;
    }
private:
    int _hour;
    int _minute;
    int _second;
};
class Date
{
private:
    // 内置类型
    int _year = 1970;
    int _month = 1;
    int _day = 1;
    // 自定义类型,将会调用此对象的拷贝构造
    Time _t;
};
int main()
{
    Date d1;
    Date d2(d1);
    return 0;
}


d1类运行的调试内部分析图(构造函数)


9a79ba3dd66a44b5856c22e575d408b9.png


d2类运行的调试内部分析图(拷贝构造函数)



bdc1d615c5f6434abdb2ae77a491abc5.png

       下面问题来了,既然有默认拷贝构造函数,我们需要不需要再定义拷贝构造函数呢?


C++拷贝构造函数和运算符重载--2      https://developer.aliyun.com/article/1424586?spm=a2c6h.13148508.setting.31.214f4f0emw3QR7

相关文章
|
3月前
|
C++
C++(十五) 运算符重载
C++中的运算符重载允许对已有运算符的功能进行重新定义,从而扩展语言功能、简化代码并提升效率。重载遵循特定语法,如 `friend 类名 operator 运算符(参数)`。重载时需注意不可新增或改变运算符数量、语义、优先级、结合性和返回类型。常见示例包括双目运算符 `+=` 和单目运算符 `-` 及 `++`。输入输出流运算符 `&lt;&lt;` 和 `&gt;&gt;` 也可重载。部分运算符只能作为成员函数重载。
|
6月前
|
C++ 容器
【C++】拷贝构造函数、拷贝赋值函数与析构函数
【C++】拷贝构造函数、拷贝赋值函数与析构函数
118 6
|
6月前
|
存储 编译器 C++
【C++】:拷贝构造函数和赋值运算符重载
【C++】:拷贝构造函数和赋值运算符重载
30 1
|
6月前
|
C++ 索引
C++核心技术要点《运算符重载》
C++核心技术要点《运算符重载》
53 2
|
5月前
|
自然语言处理 程序员 C++
C++基础知识(五:运算符重载)
运算符重载是C++中的一项强大特性,它允许程序员为自定义类型(如类或结构体)重新定义标准运算符的行为,使得这些运算符能够适用于自定义类型的操作。这样做可以增强代码的可读性和表达力,使得代码更接近自然语言,同时保持了面向对象编程的封装性。
|
5月前
|
Java 程序员 C++
|
5月前
|
编译器 C++
【C++】详解运算符重载,赋值运算符重载,++运算符重载
【C++】详解运算符重载,赋值运算符重载,++运算符重载
|
6月前
|
编译器 C++
【C++】类和对象③(类的默认成员函数:赋值运算符重载)
在C++中,运算符重载允许为用户定义的类型扩展运算符功能,但不能创建新运算符如`operator@`。重载的运算符必须至少有一个类类型参数,且不能改变内置类型运算符的含义。`.*::sizeof?`不可重载。赋值运算符`=`通常作为成员函数重载,确保封装性,如`Date`类的`operator==`。赋值运算符应返回引用并检查自我赋值。当未显式重载时,编译器提供默认实现,但这可能不足以处理资源管理。拷贝构造和赋值运算符在对象复制中有不同用途,需根据类需求定制实现。正确实现它们对避免数据错误和内存问题至关重要。接下来将探讨更多操作符重载和默认成员函数。
|
6月前
|
存储 编译器 C++
【C++】类和对象③(类的默认成员函数:拷贝构造函数)
本文探讨了C++中拷贝构造函数和赋值运算符重载的重要性。拷贝构造函数用于创建与已有对象相同的新对象,尤其在类涉及资源管理时需谨慎处理,以防止浅拷贝导致的问题。默认拷贝构造函数进行字节级复制,可能导致资源重复释放。例子展示了未正确实现拷贝构造函数时可能导致的无限递归。此外,文章提到了拷贝构造函数的常见应用场景,如函数参数、返回值和对象初始化,并指出类对象在赋值或作为函数参数时会隐式调用拷贝构造。
|
6月前
|
C++
c++进阶篇(一)——运算符重载
c++进阶篇(一)——运算符重载