面试题答案
一键面试std::unique_ptr特点
- 独占所有权:
std::unique_ptr
拥有对对象的唯一所有权,同一时刻只能有一个std::unique_ptr
指向给定对象。当std::unique_ptr
被销毁(例如离开其作用域)时,它所指向的对象也会被自动销毁。 - 不能复制:不支持拷贝构造函数和拷贝赋值运算符,只能通过移动语义来转移所有权。这使得
std::unique_ptr
非常适合用于管理动态分配的资源,避免资源泄漏。 - 性能高效:由于其简单的所有权模型,
std::unique_ptr
通常具有非常小的运行时开销,接近于普通指针。
std::shared_ptr特点
- 共享所有权:
std::shared_ptr
允许多个std::shared_ptr
指向同一个对象,通过引用计数来管理对象的生命周期。当最后一个指向对象的std::shared_ptr
被销毁时,对象才会被释放。 - 支持复制:支持拷贝构造函数和拷贝赋值运算符,每次复制都会增加引用计数。这使得
std::shared_ptr
非常适合用于需要在多个地方共享资源的场景。 - 线程安全:引用计数的递增和递减是线程安全的,因此
std::shared_ptr
可以在多线程环境中安全使用,但对象的访问和修改可能仍需要额外的同步机制。
std::weak_ptr特点
- 弱引用:
std::weak_ptr
不拥有对象的所有权,它是对std::shared_ptr
所管理对象的一个弱引用。std::weak_ptr
不会影响对象的引用计数,即不会阻止对象被销毁。 - 解决循环引用:常用于解决
std::shared_ptr
之间可能出现的循环引用问题。通过使用std::weak_ptr
打破循环引用,确保对象在不再被需要时能够正确释放。 - 过期检查:可以通过
lock()
成员函数尝试获取一个std::shared_ptr
,如果对象已被销毁(即引用计数为 0),lock()
将返回一个空的std::shared_ptr
。
std::unique_ptr适用场景举例
- 资源独占场景:当一个资源只应由一个对象管理,例如一个文件句柄。假设我们有一个
FileHandler
类用于管理文件操作,在这种情况下使用std::unique_ptr
是合适的。
#include <iostream>
#include <memory>
#include <fstream>
class FileHandler {
public:
FileHandler(const std::string& filename) : file_(std::make_unique<std::ofstream>(filename)) {
if (!file_->is_open()) {
throw std::runtime_error("Failed to open file");
}
}
~FileHandler() = default;
void write(const std::string& data) {
if (file_->is_open()) {
*file_ << data;
}
}
private:
std::unique_ptr<std::ofstream> file_;
};
在上述代码中,FileHandler
类使用 std::unique_ptr<std::ofstream>
来管理文件对象。每个 FileHandler
实例独占文件的所有权,当 FileHandler
对象被销毁时,文件会自动关闭。
std::shared_ptr适用场景举例
- 多对象共享资源场景:假设有一个图形渲染系统,其中有多个
Shape
对象可能共享一个Texture
资源。
#include <iostream>
#include <memory>
#include <string>
class Texture {
public:
Texture(const std::string& name) : name_(name) {
std::cout << "Texture " << name_ << " created" << std::endl;
}
~Texture() {
std::cout << "Texture " << name_ << " destroyed" << std::endl;
}
const std::string& getName() const {
return name_;
}
private:
std::string name_;
};
class Shape {
public:
Shape(const std::string& type, std::shared_ptr<Texture> texture) : type_(type), texture_(texture) {
std::cout << "Shape " << type_ << " created with texture " << texture_->getName() << std::endl;
}
~Shape() {
std::cout << "Shape " << type_ << " destroyed" << std::endl;
}
private:
std::string type_;
std::shared_ptr<Texture> texture_;
};
在上述代码中,多个 Shape
对象可以共享同一个 Texture
对象,Texture
对象的生命周期由 std::shared_ptr
自动管理,只有当所有指向它的 std::shared_ptr
都被销毁时,Texture
才会被释放。