目录
前言
前面我们学习了C++的一些基本的知识点,并且介绍了一些STL里面String的一些关键操作,除了这些博主还新开了一个专栏关于Linux的讲解(Linux专栏链接)大家可以关注一下,后面我会一点一点的更新的。大家坐稳扶好,要开车了!!!
拷贝函数
在我们了解深浅拷贝之前博主简单介绍一下什么是拷贝构造函数,这里只是简单的介绍一下(拷贝构造详细介绍)
是C++中的一个特殊成员函数,用于创建对象的副本。它的作用是通过使用已有对象的属性值来初始化新对象,实现对象的复制操作。通过定义拷贝构造函数,我们可以控制对象的拷贝过程,并确保正确处理含有指针或动态分配内存的类。
拷贝构造函数的定义形式如下:
cpp
类名(const 类名& 对象名)
{
// 构造函数的主体部分
// 将对象的属性值拷贝到新对象
}
拷贝构造函数的特点:拷贝构造函数在C++中具有自动调用、形参类型为const引用、逐一复制对象成员、隐式调用与显式调用、需要自定义情况等特点。
浅拷贝拷贝构造函数
浅拷贝是指简单地将一个对象的数据成员的值复制到另一个对象中,这包括基本数据类型和指针。在浅拷贝中,指针只复制了地址,而没有复制指针指向的数据。
下面我用一个简单的代码,说明C++中浅拷贝和拷贝构造函数的概念:
cpp
#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;
}
输出结果为:
cpp
Default Constructor called
Copy Constructor called
a.data: 10
b.data: 20
Destructor called
Destructor called
在上面的代码中,我们定义了一个名为 MyClass 的类,其中包含一个 int 类型的指针成员 data 。在默认构造函数中,我们创建了一个 data 指针,并将其初始化为0。在拷贝构造函数中,我们通过复制源对象的 data 指针的值来创建一个新的 data 指针。
在 main 函数中,我们首先创建一个对象 a 并将其 data 值设置为10。然后,我们使用拷贝构造函数创建了另一个对象 b ,并将其 data 值设置为与 a 相同的值。最后,我们分别输出了 a.data 和 b.data 的值。
需要注意的是,在拷贝构造函数中,我们需要手动为指针成员分配内存,并复制源对象指针的值。这是因为默认的浅拷贝只会复制指针的值,而不会创建新的内存空间。这可能会导致指向相同内存地址的多个指针,当其中一个指针释放内存时,其他指针也将失去引用的内存 。因此,在处理包含指针成员的类时,通常需要实现拷贝构造函数,并进行深拷贝(复制指针指向的数据)。这样可以确保每个对象有一份独立的数据,避免潜在的内存管理问题。
深拷贝拷贝构造函数
深拷贝是指在拷贝构造函数中创建一个新的对象,并复制源对象的所有数据成员 (包括指针指向的数据)。这样每个对象都拥有独立的内存空间,修改一个对象不会影响其他对象。
下面我用一个简单的代码,说明 C++ 中深拷贝和拷贝构造函数:
cpp
#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;
}
输出结果为:
cpp
Default Constructor called
Copy Constructor called
a.data: Hello
b.data: World
Destructor called
Destructor called
在上面的代码中,我们定义了一个名为 MyClass 的类,其中包含一个 char* 类型的指针成员 data 。在默认构造函数中,我们为 data 分配了一个字符指针,并将其初始化为空字符串。在拷贝构造函数中,我们先为 data 分配了足够的内存空间,然后使用 strcpy 函数复制源对象的字符串数据。
在 main 函数中,我们首先创建一个对象 a 并为其 data 成员分配了足够的内存空间,并将其值设置为 "Hello"。然后,我们使用拷贝构造函数创建了另一个对象 b ,并将其 data 成员的值设置为与 a 相同的值。最后,我们修改了 b 的 data 值,确保每个对象都有独立的数据。
需要注意的是,在拷贝构造函数中,我们需要手动为指针成员分配足够的内存空间,并复制源对象指针指向的数据。这样可以确保每个对象都有自己的独立副本。同时,在析构函数中,我们需要释放指针成员所占用的内存空间,避免内存泄漏。
深拷贝对于包含动态分配内存的对象非常重要,例如使用 new 或 malloc 分配的内存。通过实现深拷贝的拷贝构造函数,可以保证每个对象有独立的内存空间,避免潜在的内存管理问题,提高程序的稳定性和可靠性。
总结
本篇文章主要讨论拷贝函数的概念和使用方法。文章中涵盖了浅拷贝和深拷贝两种拷贝构造函数的介绍。
拷贝函数:拷贝函数的概念和作用。浅拷贝拷贝构造函数,解释了浅拷贝的概念,即简单地将一个对象的数据成员的值复制到另一个对象中,详细介绍了浅拷贝的拷贝构造函数的实现,提供了一个示例,展示了如何使用浅拷贝拷贝构造函数。深拷贝拷贝构造函数,解释了深拷贝的概念,即在拷贝构造函数中创建一个新的对象,并复制源对象的所有数据成员(包括指针指向的数据),详细介绍了深拷贝的拷贝构造函数的实现,提供了一个示例,展示了如何使用深拷贝拷贝构造函数。
温馨提示
感谢您对博主文章的关注与支持!在阅读本篇文章的同时,我们想提醒您留下您宝贵的意见和反馈。如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!