代码随想录八股训练营第三十三天| C++
前言
一、深拷贝和浅拷贝的区别?
1.1.浅拷贝(Shallow Copy):
1.2.深拷贝(Deep Copy):
1.3.实现深拷贝和浅拷贝的方式包括:
二、STL容器有哪些??
2.1.序列容器(Sequence Containers):
2.2. 关联容器(Associative Containers):
2.3.容器适配器(Container Adapters):
2.4. 特殊容器:
2.5. 并发容器(C++11及以后版本):
总结
前言
在C++编程语言中,构造函数和析构函数是类的特殊成员函数,它们在对象的生命周期中扮演着至关重要的角色。构造函数负责初始化对象,而析构函数则负责在对象生命周期结束时进行清理工作。理解这些函数的类型和作用对于编写高效、安全的C++程序至关重要。
一、深拷贝和浅拷贝的区别?
在编程中,深拷贝和浅拷贝是两种不同的对象复制方式,它们的主要区别在于复制对象时对引用类型的处理。
1.1.浅拷贝(Shallow Copy):
- 浅拷贝仅复制对象的非动态分配的成员变量的值。
- 对于动态分配的内存(如指针指向的内存),浅拷贝只是复制指针的值,而不是指针指向的数据。
- 这意味着原始对象和拷贝对象共享同一块动态分配的内存。
- 如果其中一个对象修改了这块内存,另一个对象看到的也是修改后的数据。
1.2.深拷贝(Deep Copy):
- 深拷贝不仅复制非动态分配的成员变量的值,还会为动态分配的内存分配新的内存,并复制数据到新内存中。
- 这样,原始对象和拷贝对象拥有完全独立的内存空间。
- 修改一个对象的动态内存不会影响另一个对象。
1.3.实现深拷贝和浅拷贝的方式包括:
-
赋值操作符:通过重载赋值操作符(
operator=
),可以控制对象拷贝的行为。如果只复制指针而不分配新内存,则是浅拷贝;如果为每个指针分配新内存并复制数据,则是深拷贝。 -
拷贝构造函数:通过重载拷贝构造函数,可以控制对象在创建时的拷贝行为。同样,可以选择实现浅拷贝或深拷贝。
-
使用标准库:对于某些标准库类型(如
std::string
),库已经提供了深拷贝的实现。 -
手动管理内存:在需要深拷贝自定义类型时,可能需要手动为动态分配的内存分配新空间并复制内容。
#include <iostream>
#include <cstring>
class ShallowCopy {
public:
int* data;
ShallowCopy(int val) {
data = new int(val);
}
// 浅拷贝构造函数
ShallowCopy(const ShallowCopy& other) {
data = other.data;
}
// 浅拷贝赋值操作符
ShallowCopy& operator=(const ShallowCopy& other) {
if (this != &other) {
data = other.data;
}
return *this;
}
~ShallowCopy() {
delete data;
}
};
class DeepCopy {
public:
int* data;
DeepCopy(int val) {
data = new int(val);
}
// 深拷贝构造函数
DeepCopy(const DeepCopy& other) {
data = new int(*(other.data));
}
// 深拷贝赋值操作符
DeepCopy& operator=(const DeepCopy& other) {
if (this != &other) {
delete data;
data = new int(*(other.data));
}
return *this;
}
~DeepCopy() {
delete data;
}
};
int main() {
ShallowCopy sc1(10);
ShallowCopy sc2 = sc1; // 浅拷贝
sc2.data = new int(20); // 修改sc2会影响到sc1
DeepCopy dc1(10);
DeepCopy dc2 = dc1; // 深拷贝
dc2.data = new int(20); // 修改dc2不会影响到dc1
return 0;
}
二、STL容器有哪些??
C++标准模板库(STL,Standard Template Library)提供了一组非常有用的容器,用于存储和管理数据集合。以下是一些常用的STL容器:
2.1.序列容器(Sequence Containers):
std::vector
:动态数组,支持快速随机访问。std::deque
(双端队列):支持快速的前端和后端访问以及插入和删除。std::list
:双向链表,支持高效的节点插入和删除。std::forward_list
:单向链表,支持高效的节点插入和删除。
2.2. 关联容器(Associative Containers):
std::set
:基于红黑树实现的集合,元素自动排序。std::multiset
:允许多个元素值相同的集合。std::map
:基于红黑树实现的键值对集合,键自动排序。std::multimap
:允许多个元素具有相同键的键值对集合。std::unordered_set
:基于哈希表实现的集合,不保证元素顺序。std::unordered_multiset
:允许多个元素值相同的无序集合。std::unordered_map
:基于哈希表实现的键值对集合,不保证键的顺序。std::unordered_multimap
:允许多个元素具有相同键的无序键值对集合。
2.3.容器适配器(Container Adapters):
std::stack
:后进先出(LIFO)的栈。std::queue
:先进先出(FIFO)的队列。std::priority_queue
:最大元素优先的队列。
2.4. 特殊容器:
std::array
:固定大小的数组。std::bitset
:固定大小的位向量。
2.5. 并发容器(C++11及以后版本):
std::future
:用于异步操作的结果。std::thread
:用于创建和管理线程。std::mutex
:用于线程同步的互斥锁。std::condition_variable
:用于线程间的同步。
总结
构造函数和析构函数是C++中用于管理对象生命周期的关键工具。构造函数有多种类型,包括默认构造函数、参数化构造函数、拷贝构造函数、移动构造函数、委托构造函数和转换构造函数,每种都有其特定的用途和场景。默认构造函数用于无参数初始化,参数化构造函数允许带参数的初始化,拷贝构造函数用于创建对象的副本,移动构造函数用于资源的移动,委托构造函数通过调用其他构造函数简化代码,而转换构造函数则用于类型转换。需要注意的是,构造函数不能是虚函数,因为它们在对象类型完全确定之前就被调用。相反,析构函数可以是虚函数,这在处理继承和多态时非常重要,以确保正确地释放资源并避免资源泄露。正确地使用这些构造函数和析构函数可以提高代码的灵活性和效率,是每个C++程序员必须掌握的基础知识。