代码随想录八股训练营第三十三天| 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++程序员必须掌握的基础知识。

第二十二的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值