【C++基础(六)】类和对象(中) --拷贝构造,运算符重载(上)

简介: 【C++基础(六)】类和对象(中) --拷贝构造,运算符重载

💓博主CSDN主页:杭电码农-NEO💓


⏩专栏分类:C++初阶之路


🚚代码仓库:NEO的学习日记🚚


🌹关注我🫵带你学习C++

  🔝🔝



1. 前言

本章重点:

本篇文章将详细讲解拷贝构造函数
和运算符重载,并介绍const成员的概念

拷贝构造函数和运算符重载
是类和对象中六大默认成员函数
的其中两个

拷贝构造类似于构造一个一模一样的你


2. 拷贝构造函数

我们在写代码的时候会遇见这种场景:

class Date
{
public:
   Date(int year = 1900, int month = 1, int day = 1)
   {
   _year = year;
   _month = month;
   _day = day;
   }
private:
   int _year;
   int _month;
   int _day;
};
int main()
{
   Date d1(2023,7,30);
   Date d2(d1);//用d1初始化d2
   return 0;
}

使用一个已经存在的对象初始化
一个正在定义的对象就是在拷贝构造!

拷贝构造函数特征:

  • 拷贝构造是构造函数的一个重载形式
  • 拷贝构造函数只能有一个参数且必须
    是类类型对象的引用!

比如Date类的拷贝构造:

Date(const Date& d)
 {
   _year = d._year;
   _month = d._month;
   _day = d._day;
 }

2.1 对拷贝构造函数参数的思考

为什么拷贝构造函数的参数
一定要是:类类型对象的引用?

因为拷贝构造是用另一个对象初始化

所以是类类型对象可以理解
但是为啥必须传引用?

这是因为不传引用会引起无限递归!

可以这样理解无限递归:

假如加上了引用,调用拷贝构造时
传对象的别名进函数,就不会有
形参拷贝一份实参的过程,就不会死递归!

所以拷贝构造函数一定要加上引用!


2.2 默认拷贝构造函数

如果用户不显示写拷贝构造函数
编译器会自动生成一个默认构造函数

默认构造函数会对内置类型完成:
值拷贝(浅拷贝)

默认构造函数会去调用自定义
类型的构造函数完成拷贝

对于内置类型来说,浅拷贝可能会有问题!

举个例子:

class Stack
{
public:
 Stack(size_t capacity = 10)//构造函数
 {
   _array = (DataType*)malloc(capacity * sizeof(DataType));
   if (nullptr == _array)
   {
   perror("malloc申请空间失败");
   return;
   }
   _size = 0;
   _capacity = capacity;
 }
 void Push(const int& data)//插入函数
 {
   _array[_size] = data;
   _size++;
 }
 ~Stack()//析构函数
 {
   if (_array)
   {
     free(_array);
     _array = nullptr;
     _capacity = 0;
     _size = 0;
   }
 }
private:
   int *_array;
   size_t _size;
   size_t _capacity;
};
int main()
{
  Stack s1(10);
  s1.push(1);
  s1.push(2);
  s3.push(3);
  s3.push(4);
  s3.push(5);
  Stack s2(s1);
  retrn 0;
}

stack类没有显示写拷贝构造函数

编译器会自动生成默认拷贝构造函数

默认构造函数是按照字节方式直接拷贝的

所以对象s1和s2的关系图如下:

array指向的空间是动态开辟的
是在堆区存储的,使用值拷贝的方式
s1和s2中的array指向的空间相同!

这么做会有啥问题?

当s1和s2生命周期结束时
会分别调用它们各自的析构函数
然而两个对象中的指针指向的空间相同
析构函数会调用两个free释放空间!
同一份空间释放两个就会出错!


2.3 对拷贝构造函数的总结

  • 拷贝构造函数的参数必须是引用
  • 若类中没有涉及到空间申请
    则默认拷贝构造就够用了
  • 下面这两种写法都是在拷贝构造:
Date d1(2023,7,30);
Date d2(d1);
Date d3 = d1;

拷贝构造的典型应用场景:

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

相关文章
|
6天前
|
C++ 容器
C++中自定义结构体或类作为关联容器的键
C++中自定义结构体或类作为关联容器的键
13 0
|
5天前
|
存储 安全 编译器
【C++】类和对象(下)
【C++】类和对象(下)
【C++】类和对象(下)
|
4天前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
4天前
|
编译器 C++
virtual类的使用方法问题之静态和非静态函数成员在C++对象模型中存放如何解决
virtual类的使用方法问题之静态和非静态函数成员在C++对象模型中存放如何解决
|
4天前
|
编译器 C++
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
|
5天前
|
编译器 C++
【C++】类和对象(中)
【C++】类和对象(中)
|
5天前
|
存储 编译器 程序员
【C++】类和对象(上)
【C++】类和对象(上)
|
6天前
|
存储 编译器 C++
【C++】类和对象(下)
【C++】类和对象(下)
|
6天前
|
存储 算法 搜索推荐
【C++】类的默认成员函数
【C++】类的默认成员函数
|
11天前
|
C++
C++ --> 类和对象(三)
C++ --> 类和对象(三)
26 9