【C++入门到精通】C++入门 —— 深浅拷贝函数

简介: 是C++中的一个特殊成员函数,用于创建对象的副本。它的作用是通过使用已有对象的属性值来初始化新对象,实现对象的复制操作。通过定义拷贝构造函数,我们可以控制对象的拷贝过程,并确保正确处理含有指针或动态分配内存的类。

 目录

拷贝函数

浅拷贝拷贝构造函数

深拷贝拷贝构造函数

总结


前言

       前面我们学习了C++的一些基本的知识点,并且介绍了一些STL里面String的一些关键操作,除了这些博主还新开了一个专栏关于Linux的讲解(Linux专栏链接)大家可以关注一下,后面我会一点一点的更新的。大家坐稳扶好,要开车了!!!

拷贝函数

       在我们了解深浅拷贝之前博主简单介绍一下什么是拷贝构造函数,这里只是简单的介绍一下(拷贝构造详细介绍

       是C++中的一个特殊成员函数,用于创建对象的副本。它的作用是通过使用已有对象的属性值来初始化新对象,实现对象的复制操作。通过定义拷贝构造函数,我们可以控制对象的拷贝过程,并确保正确处理含有指针或动态分配内存的类。

拷贝构造函数的定义形式如下:

类名(const 类名& 对象名)
{
    // 构造函数的主体部分
    // 将对象的属性值拷贝到新对象
}

image.gif

        拷贝构造函数的特点:拷贝构造函数在C++中具有自动调用、形参类型为const引用、逐一复制对象成员、隐式调用与显式调用、需要自定义情况等特点

浅拷贝拷贝构造函数

       浅拷贝是指简单地将一个对象的数据成员的值复制到另一个对象中,这包括基本数据类型和指针。在浅拷贝中,指针只复制了地址,而没有复制指针指向的数据

下面我用一个简单的代码,说明C++中浅拷贝和拷贝构造函数的概念:

#include <iostream>
class MyClass {
public:
  int* data;
  // 默认构造函数
  MyClass() {
    data = new int(0);
    std::cout << "Default Constructor called" << std::endl;
  }
  // 拷贝构造函数
  MyClass(const MyClass& obj) {
    data = new int(*(obj.data));
    std::cout << "Copy Constructor called" << std::endl;
  }
  // 析构函数
  ~MyClass() {
    delete data;
    std::cout << "Destructor called" << std::endl;
  }
};
int main() {
  // 创建对象a
  MyClass a;
  *(a.data) = 10;
  // 使用拷贝构造函数创建对象b
  MyClass b(a);
  // 修改对象b的值
  *(b.data) = 20;
  // 输出结果
  std::cout << "a.data: " << *(a.data) << std::endl;
  std::cout << "b.data: " << *(b.data) << std::endl;
  return 0;
}

image.gif

输出结果为:

Default Constructor called
Copy Constructor called
a.data: 10
b.data: 20
Destructor called
Destructor called

image.gif

       在上面的代码中,我们定义了一个名为 MyClass 的类,其中包含一个 int 类型的指针成员 data 。在默认构造函数中,我们创建了一个 data 指针,并将其初始化为0。在拷贝构造函数中,我们通过复制源对象的 data 指针的值来创建一个新的 data 指针。

main 函数中,我们首先创建一个对象 a 并将其 data 值设置为10。然后,我们使用拷贝构造函数创建了另一个对象 b ,并将其 data 值设置为与 a 相同的值。最后,我们分别输出了 a.datab.data 的值。

       需要注意的是,在拷贝构造函数中,我们需要手动为指针成员分配内存,并复制源对象指针的值。这是因为默认的浅拷贝只会复制指针的值,而不会创建新的内存空间。这可能会导致指向相同内存地址的多个指针,当其中一个指针释放内存时,其他指针也将失去引用的内存。因此,在处理包含指针成员的类时,通常需要实现拷贝构造函数,并进行深拷贝(复制指针指向的数据)。这样可以确保每个对象有一份独立的数据,避免潜在的内存管理问题。

深拷贝拷贝构造函数

       深拷贝是指在拷贝构造函数中创建一个新的对象,并复制源对象的所有数据成员包括指针指向的数据)。这样每个对象都拥有独立的内存空间,修改一个对象不会影响其他对象。

下面我用一个简单的代码,说明 C++ 中深拷贝和拷贝构造函数:

#include <iostream>
#include <cstring>
class MyClass {
public:
  char* data;
  // 默认构造函数
  MyClass() {
    data = new char[1];
    *data = '\0';
    std::cout << "Default Constructor called" << std::endl;
  }
  // 拷贝构造函数
  MyClass(const MyClass& obj) {
    data = new char[strlen(obj.data) + 1];
    strcpy(data, obj.data);
    std::cout << "Copy Constructor called" << std::endl;
  }
  // 析构函数
  ~MyClass() {
    delete[] data;
    std::cout << "Destructor called" << std::endl;
  }
};
int main() {
  // 创建对象a
  MyClass a;
  a.data = new char[5];
  strcpy(a.data, "Hello");
  // 使用拷贝构造函数创建对象b
  MyClass b(a);
  // 修改对象b的值
  delete[] b.data;
  b.data = new char[6];
  strcpy(b.data, "World");
  // 输出结果
  std::cout << "a.data: " << a.data << std::endl;
  std::cout << "b.data: " << b.data << std::endl;
  return 0;
}

image.gif

输出结果为:

Default Constructor called
Copy Constructor called
a.data: Hello
b.data: World
Destructor called
Destructor called

image.gif

       在上面的代码中,我们定义了一个名为  MyClass  的类,其中包含一个  char*  类型的指针成员  data 。在默认构造函数中,我们为  data  分配了一个字符指针,并将其初始化为空字符串。在拷贝构造函数中,我们先为  data  分配了足够的内存空间,然后使用  strcpy  函数复制源对象的字符串数据。

       在  main  函数中,我们首先创建一个对象  a  并为其  data  成员分配了足够的内存空间,并将其值设置为 "Hello"。然后,我们使用拷贝构造函数创建了另一个对象  b ,并将其  data  成员的值设置为与  a  相同的值。最后,我们修改了  b  的  data  值,确保每个对象都有独立的数据。

       需要注意的是,在拷贝构造函数中,我们需要手动为指针成员分配足够的内存空间,并复制源对象指针指向的数据。这样可以确保每个对象都有自己的独立副本。同时,在析构函数中,我们需要释放指针成员所占用的内存空间,避免内存泄漏

       深拷贝对于包含动态分配内存的对象非常重要,例如使用  new  或  malloc  分配的内存。通过实现深拷贝的拷贝构造函数,可以保证每个对象有独立的内存空间,避免潜在的内存管理问题,提高程序的稳定性和可靠性

总结

       本篇文章主要讨论拷贝函数的概念和使用方法。文章中涵盖了浅拷贝和深拷贝两种拷贝构造函数的介绍。

       拷贝函数:拷贝函数的概念和作用。浅拷贝拷贝构造函数,解释了浅拷贝的概念,即简单地将一个对象的数据成员的值复制到另一个对象中,详细介绍了浅拷贝的拷贝构造函数的实现,提供了一个示例,展示了如何使用浅拷贝拷贝构造函数。深拷贝拷贝构造函数,解释了深拷贝的概念,即在拷贝构造函数中创建一个新的对象,并复制源对象的所有数据成员(包括指针指向的数据),详细介绍了深拷贝的拷贝构造函数的实现,提供了一个示例,展示了如何使用深拷贝拷贝构造函数。

温馨提示

       感谢您对博主文章的关注与支持!在阅读本篇文章的同时,我们想提醒您留下您宝贵的意见和反馈。如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!

       再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!

image.gif编辑

目录
相关文章
|
1月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
36 2
C++入门12——详解多态1
|
21天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
44 6
|
1月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
21 0
C++ 多线程之线程管理函数
|
1月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
79 1
|
1月前
|
程序员 C语言 C++
C++入门5——C/C++动态内存管理(new与delete)
C++入门5——C/C++动态内存管理(new与delete)
59 1
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
135 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
38 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
25天前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
17 0
|
25天前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
21 0