面试题答案
一键面试std::unique_ptr、std::shared_ptr 和 std::weak_ptr 的主要区别
- 所有权:
- std::unique_ptr:拥有对对象的唯一所有权。一旦 std::unique_ptr 被销毁,它所指向的对象也会被销毁。它不能被复制,但可以转移所有权。
- std::shared_ptr:允许多个指针共享对一个对象的所有权。通过引用计数机制来管理对象的生命周期,当引用计数为 0 时,对象被自动销毁。
- std::weak_ptr:不拥有对象的所有权,它是对 std::shared_ptr 所管理对象的一种弱引用。它不会增加对象的引用计数,主要用于解决 std::shared_ptr 中的循环引用问题,避免内存泄漏。
- 性能:
- std::unique_ptr:由于其简单的所有权模型,通常具有最小的运行时开销,性能较好。
- std::shared_ptr:由于需要维护引用计数,开销相对较大,尤其是在多线程环境下,引用计数的更新需要额外的同步操作。
- std::weak_ptr:开销主要在于创建和销毁时与 std::shared_ptr 的交互,本身不影响对象的生命周期管理。
- 应用场景:
- std::unique_ptr:适用于对象只应由一个所有者管理的场景,例如函数内部局部对象的管理,或资源的独占式管理。
- std::shared_ptr:适用于对象需要被多个部分共享的场景,如在多个模块间传递对象的所有权。
- std::weak_ptr:通常与 std::shared_ptr 一起使用,用于打破循环引用,或在对象可能被释放的情况下安全地访问对象。
使用 std::unique_ptr 在类继承体系中管理派生类对象
#include <iostream>
#include <memory>
class Base {
public:
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
}
};
class Derived : public Base {
public:
~Derived() {
std::cout << "Derived destructor" << std::endl;
}
};
void testUniquePtr() {
std::unique_ptr<Base> ptr = std::make_unique<Derived>();
// 这里可以通过ptr访问Base类和Derived类的成员函数
// 当ptr离开作用域时,Derived对象会被自动销毁
}
int main() {
testUniquePtr();
return 0;
}
在上述代码中:
- 创建对象:使用
std::make_unique<Derived>()
创建一个Derived
对象,并将其所有权转移给std::unique_ptr<Base>
类型的ptr
。std::make_unique
是 C++14 引入的函数,用于更安全和高效地创建std::unique_ptr
。 - 内存管理:当
ptr
离开其作用域(testUniquePtr
函数结束)时,Derived
对象会被自动销毁,从而确保了内存安全,避免了悬空指针和内存泄漏。由于Base
类有虚析构函数,Derived
类的析构函数会被正确调用。