1) 移动语义和拷贝语义的区别
拷贝语义和移动语义是C++中对象所有权管理的两种机制,主要在对象初始化、赋值或传参时体现。
拷贝语义 (Copy Semantics)
- 行为:通过深拷贝或浅拷贝,创建一个新对象,并将原对象的值或资源复制到新对象。
- 应用场景:用于保证两个对象完全独立,尤其是在需要保留源对象时。
- 特点:
- 使用拷贝构造函数 (
T(const T&)
) 或拷贝赋值运算符 (T& operator=(const T&)
)。 - 原对象和副本对象都拥有资源的独立副本。
- 适合没有涉及动态资源管理的简单类。
- 使用拷贝构造函数 (
例子:
std::string str1 = "Hello"; std::string str2 = str1; // 拷贝语义:str2是str1的副本
移动语义 (Move Semantics)
- 行为:通过转移资源所有权,避免不必要的拷贝,提高性能。
- 应用场景:适用于临时对象(如返回值或右值),当源对象可以丢弃时。
- 特点:
- 使用移动构造函数 (
T(T&&)
) 或移动赋值运算符 (T& operator=(T&&)
)。 - 源对象的资源被转移给目标对象,通常源对象会被重置为默认状态。
- 大幅减少资源分配和释放的开销。
- 使用移动构造函数 (
例子:
std::string str1 = "Hello";
std::string str2 = std::move(str1);
// 移动语义:str2接管了str1的资源,str1可能为空
区别对比
特点 | 拷贝语义 | 移动语义 |
---|---|---|
是否创建新资源 | 是 | 否(资源转移) |
性能开销 | 高(需要分配新资源并复制内容) | 低(只转移指针或资源句柄) |
资源所有权 | 独立拥有 | 目标对象接管源对象资源 |
使用条件 | 源对象不可丢弃 | 源对象可丢弃或不需要再使用 |
2) 什么是C++中的智能指针?有哪些类型的智能指针?
智能指针 (Smart Pointer)
- 智能指针是C++标准库(
<memory>
)提供的一种类模板,用于自动管理动态分配的内存资源。 - 它通过RAII(资源获取即初始化)机制,自动在合适的时机释放内存,避免内存泄漏。
- 智能指针包装了原生指针,支持类似指针的操作(如
*
和->
),但拥有更安全和自动化的内存管理。
常见类型的智能指针
-
std::unique_ptr
- 特点:
- 独占所有权:一个
unique_ptr
对象独享其管理的资源,不能被复制。 - 只能通过移动语义转移资源所有权。
- 独占所有权:一个
- 适用场景:需要独占资源且生命周期明确的场景。
- 例子:
std::unique_ptr<int> p1 = std::make_unique<int>(42); std::unique_ptr<int> p2 = std::move(p1); // p1失效,p2接管资源
- 特点:
-
std::shared_ptr
- 特点:
- 共享所有权:多个
shared_ptr
可以共享同一资源,资源会在最后一个shared_ptr
销毁时自动释放。 - 内部通过引用计数跟踪资源的使用。
- 共享所有权:多个
- 适用场景:需要多个对象共享同一资源的场景。
- 例子:
std::shared_ptr<int> p1 = std::make_shared<int>(42); std::shared_ptr<int> p2 = p1; // p1和p2共享同一资源
- 特点:
-
std::weak_ptr
- 特点:
- 弱引用:不影响资源的引用计数,只能与
shared_ptr
配合使用。 - 可用于打破循环引用。
- 弱引用:不影响资源的引用计数,只能与
- 适用场景:需要观测资源状态但不控制资源生命周期的场景。
- 例子:
std::shared_ptr<int> shared = std::make_shared<int>(42); std::weak_ptr<int> weak = shared; // 不增加引用计数 if (auto sp = weak.lock()) {// 检查资源是否仍然有效 std::cout << *sp << std::endl; }
- 特点:
智能指针的选择建议
- 使用
std::unique_ptr
管理独占资源。 - 使用
std::shared_ptr
在共享资源场景中。 - 使用
std::weak_ptr
打破循环引用或实现弱引用关系。
通过合理使用智能指针,可以显著减少手动内存管理带来的复杂性和错误风险。