面试题答案
一键面试std::unique_ptr
std::unique_ptr
是一种独占式智能指针,它拥有对所指向对象的唯一所有权。当 std::unique_ptr
被销毁时,它所指向的对象也会被自动销毁,从而防止内存泄漏。
场景及示例
适合于一个对象只应由一个所有者管理的场景,比如管理一个文件句柄。
#include <iostream>
#include <memory>
class File {
public:
File(const char* filename) {
std::cout << "Opening file: " << filename << std::endl;
}
~File() {
std::cout << "Closing file" << std::endl;
}
};
int main() {
std::unique_ptr<File> filePtr(new File("example.txt"));
// 这里filePtr拥有File对象的唯一所有权
// 当filePtr离开作用域时,File对象会被自动销毁
return 0;
}
防止内存泄漏机制
std::unique_ptr
利用RAII(Resource Acquisition Is Initialization)原则,在构造时获取资源(分配内存),在析构时释放资源(释放内存)。由于它是独占式的,不存在多个指针指向同一对象导致重复释放或内存泄漏的问题。
std::shared_ptr
std::shared_ptr
允许多个指针共享对同一对象的所有权。它使用引用计数来跟踪有多少个 std::shared_ptr
指向同一个对象。当引用计数降为0时,对象会被自动销毁。
场景及示例
适用于多个对象需要共享同一块资源的场景,例如在实现共享数据结构时。
#include <iostream>
#include <memory>
class SharedData {
public:
SharedData() {
std::cout << "SharedData created" << std::endl;
}
~SharedData() {
std::cout << "SharedData destroyed" << std::endl;
}
};
int main() {
std::shared_ptr<SharedData> ptr1 = std::make_shared<SharedData>();
std::shared_ptr<SharedData> ptr2 = ptr1; // ptr2和ptr1共享同一个SharedData对象
std::cout << "Use count of ptr1: " << ptr1.use_count() << std::endl;
std::cout << "Use count of ptr2: " << ptr2.use_count() << std::endl;
// 当ptr1和ptr2离开作用域时,引用计数降为0,SharedData对象被销毁
return 0;
}
防止内存泄漏机制
通过引用计数机制,每次复制 std::shared_ptr
时,引用计数增加;每次 std::shared_ptr
被销毁时,引用计数减少。当引用计数为0时,对象的内存被自动释放,避免了内存泄漏。
std::weak_ptr
std::weak_ptr
是一种弱引用,它指向由 std::shared_ptr
管理的对象,但不增加引用计数。它主要用于解决 std::shared_ptr
之间的循环引用问题,防止内存泄漏。
场景及示例
假设有两个类 A
和 B
,它们相互引用,可能会导致循环引用。
#include <iostream>
#include <memory>
class B;
class A {
public:
std::weak_ptr<B> bPtr;
~A() {
std::cout << "A destroyed" << std::endl;
}
};
class B {
public:
std::shared_ptr<A> aPtr;
~B() {
std::cout << "B destroyed" << std::endl;
}
};
int main() {
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->bPtr = b;
b->aPtr = a;
// 如果不使用weak_ptr,a和b之间会形成循环引用,导致内存泄漏
// 这里a和b离开作用域时,它们指向的对象能正确销毁
return 0;
}
防止内存泄漏机制
std::weak_ptr
不增加引用计数,因此不会干扰 std::shared_ptr
的引用计数机制。当 std::shared_ptr
的引用计数降为0时,对象会被销毁,即使有 std::weak_ptr
指向它。std::weak_ptr
可以通过 lock()
方法尝试获取一个 std::shared_ptr
,如果对象还存在,lock()
会返回一个有效的 std::shared_ptr
,否则返回一个空指针。这有助于在需要时安全地访问由 std::shared_ptr
管理的对象,同时避免循环引用导致的内存泄漏。