答案:std::unique_ptr通过独占所有权和RAII原则管理资源,确保同一时间仅一个指针拥有资源,避免内存泄漏;支持自定义删除器以管理非内存资源如文件句柄;可安全转换为std::shared_ptr以实现共享所有权,但需用std::move转移所有权,且应优先使用unique_ptr以减少开销。

C++中,
std::unique_ptr
unique_ptr
unique_ptr
要使用
unique_ptr
我们通常会通过
std::make_unique
unique_ptr
#include <memory>
#include <iostream>
class MyResource {
public:
MyResource(int id) : id_(id) {
std::cout << "MyResource " << id_ << " created." << std::endl;
}
~MyResource() {
std::cout << "MyResource " << id_ << " destroyed." << std::endl;
}
void doSomething() {
std::cout << "MyResource " << id_ << " doing something." << std::endl;
}
private:
int id_;
};
int main() {
// 1. 创建 unique_ptr
// 推荐使用 std::make_unique,更安全高效
auto ptr1 = std::make_unique<MyResource>(1);
ptr1->doSomething();
// 2. 所有权转移:unique_ptr 是不可复制的,只能通过移动语义转移所有权
// auto ptr2 = ptr1; // 编译错误!
std::unique_ptr<MyResource> ptr2 = std::move(ptr1);
if (ptr1 == nullptr) { // ptr1 现在是空的
std::cout << "ptr1's ownership has been moved." << std::endl;
}
ptr2->doSomething();
// 3. 获取原始指针 (get()),但不转移所有权
MyResource* rawPtr = ptr2.get();
if (rawPtr) {
rawPtr->doSomething();
}
// 4. 释放所有权 (release()),返回原始指针,unique_ptr 变为空
// 现在需要手动管理 rawPtr_released
MyResource* rawPtr_released = ptr2.release();
if (ptr2 == nullptr) {
std::cout << "ptr2 has released its ownership." << std::endl;
}
delete rawPtr_released; // 必须手动删除!
// 5. 重置 unique_ptr (reset()),释放当前资源并可以指向新资源
auto ptr3 = std::make_unique<MyResource>(3);
std::cout << "ptr3 holds resource 3." << std::endl;
ptr3.reset(new MyResource(4)); // 释放资源3,管理新资源4
std::cout << "ptr3 now holds resource 4." << std::endl;
// 如果 reset 不带参数,则释放当前资源并变为空
ptr3.reset();
if (ptr3 == nullptr) {
std::cout << "ptr3 is now empty." << std::endl;
}
// 6. unique_ptr 离开作用域时自动销毁资源 (MyResource 2)
{
auto ptr_scope = std::make_unique<MyResource>(2);
std::cout << "Inside scope." << std::endl;
} // ptr_scope 在这里超出作用域,MyResource 2 被销毁
std::cout << "Outside scope." << std::endl;
return 0;
}这段代码展示了
unique_ptr
std::move
立即学习“C++免费学习笔记(深入)”;
unique_ptr
shared_ptr
在我看来,理解
unique_ptr
shared_ptr
unique_ptr
unique_ptr
std::move
unique_ptr
unique_ptr
而
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
所以,我通常的经验是,优先考虑 unique_ptr
unique_ptr
shared_ptr
shared_ptr
weak_ptr
unique_ptr
unique_ptr
FILE*
当
unique_ptr
delete
unique_ptr
unique_ptr
自定义删除器可以是一个函数对象(包括Lambda表达式)或一个普通函数指针。
例如,管理
FILE*
#include <memory>
#include <cstdio> // For FILE, fopen, fclose
#include <iostream>
// 自定义删除器:一个Lambda表达式
auto file_closer = [](FILE* file_ptr) {
if (file_ptr) {
std::cout << "Closing file handle..." << std::endl;
fclose(file_ptr);
}
};
// unique_ptr 的类型需要指定资源类型和删除器类型
// std::unique_ptr<FILE, decltype(file_closer)>
using UniqueFilePtr = std::unique_ptr<FILE, decltype(file_closer)>;
void processFile(const char* filename) {
FILE* f = fopen(filename, "r");
if (!f) {
std::cerr << "Failed to open file: " << filename << std::endl;
return;
}
// 使用自定义删除器创建 unique_ptr
UniqueFilePtr file_res(f, file_closer);
char buffer[256];
if (fgets(buffer, sizeof(buffer), file_res.get())) {
std::cout << "Read from file: " << buffer;
} else {
std::cout << "Could not read from file or file is empty." << std::endl;
}
// file_res 在这里超出作用域时,file_closer 会被调用,自动关闭文件
std::cout << "File processing finished." << std::endl;
}
int main() {
// 创建一个临时文件用于测试
FILE* temp_file = fopen("temp.txt", "w");
if (temp_file) {
fprintf(temp_file, "Hello from unique_ptr!\n");
fclose(temp_file);
}
processFile("temp.txt");
// 顺便提一下,unique_ptr 也可以管理数组
// unique_ptr<T[]> 类型会自动使用 delete[]
auto intArray = std::make_unique<int[]>(5);
for (int i = 0; i < 5; ++i) {
intArray[i] = i * 10;
std::cout << intArray[i] << " ";
}
std::cout << std::endl;
// intArray 在这里超出作用域时,会自动调用 delete[] intArray;
return 0;
}这里的关键是
UniqueFilePtr
unique_ptr
FILE*
file_closer
processFile
对于数组,
unique_ptr
std::unique_ptr<T[]>
delete[]
delete
new[]
delete[]
unique_ptr
shared_ptr
将
unique_ptr
shared_ptr
举个例子,你可能在一个工厂函数中创建了一个对象,这个工厂函数返回一个
unique_ptr
unique_ptr
shared_ptr
如何安全地实现转换:
C++11 提供了直接从
unique_ptr
shared_ptr
unique_ptr
#include <memory>
#include <iostream>
#include <vector>
class Gadget {
public:
Gadget(int id) : id_(id) {
std::cout << "Gadget " << id_ << " created." << std::endl;
}
~Gadget() {
std::cout << "Gadget " << id_ << " destroyed." << std::endl;
}
void use() {
std::cout << "Using Gadget " << id_ << std::endl;
}
private:
int id_;
};
// 模拟一个工厂函数,创建并返回一个独占的Gadget
std::unique_ptr<Gadget> createGadget(int id) {
std::cout << "Factory creating Gadget " << id << std::endl;
return std::make_unique<Gadget>(id);
}
// 模拟一个管理器,它需要共享所有权
std::vector<std::shared_ptr<Gadget>> global_gadget_registry;
void registerGadget(std::shared_ptr<Gadget> gadget) {
std::cout << "Registering Gadget " << gadget->id_ << " into global registry." << std::endl;
global_gadget_registry.push_back(std::move(gadget));
}
int main() {
// 1. 创建一个 unique_ptr
auto unique_g1 = createGadget(101);
unique_g1->use();
// 2. 将 unique_ptr 转换为 shared_ptr
// 注意:unique_g1 必须通过 std::move 转移所有权
std::shared_ptr<Gadget> shared_g1 = std::move(unique_g1);
if (unique_g1 == nullptr) {
std::cout << "Original unique_g1 is now empty after conversion." << std::endl;
}
shared_g1->use(); // shared_g1 现在拥有了资源
// 3. 将这个 shared_ptr 注册到需要共享所有权的地方
registerGadget(shared_g1); // shared_g1 仍然有效,因为它被复制到了vector中
// 4. 再次创建一个 unique_ptr,并直接转换为 shared_ptr 传递
registerGadget(std::move(createGadget(102))); // 临时 unique_ptr 转换为 shared_ptr
std::cout << "Exiting main function." << std::endl;
// 当 main 函数结束时,global_gadget_registry 中的 shared_ptr 也会被销毁
// 最终 Gadget 101 和 102 会被销毁
return 0;
}在这个例子中,
std::move(unique_g1)
unique_ptr
shared_ptr
unique_ptr
unique_g1
shared_ptr
shared_g1
需要注意的是,这种转换会引入
shared_ptr
unique_ptr
以上就是C++如何使用unique_ptr实现独占式资源管理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号