C++的<memory>
库是标准模板库(STL)的一部分,它提供了用于动态内存管理、智能指针、内存分配器等功能的工具。以下是详细介绍 <memory>
库的使用方法,涵盖其主要概念和函数。
1. 智能指针
智能指针是 <memory>
库的核心内容,用于自动管理动态分配的内存,避免内存泄漏和悬空指针等问题。
1.1 std::unique_ptr
std::unique_ptr
是一个独占所有权的智能指针,它确保同一时间只有一个指针指向动态分配的对象。
-
创建和初始化
#include <memory> #include <iostream> int main() { // 创建一个指向动态分配对象的 unique_ptr std::unique_ptr<int> ptr1(new int(10)); std::cout << *ptr1 << std::endl; // 输出 10 // 使用 make_unique 创建 unique_ptr(推荐) auto ptr2 = std::make_unique<int>(20); std::cout << *ptr2 << std::endl; // 输出 20 }
std::make_unique
是 C++17 引入的,它比直接使用new
更安全,因为它不会导致双重分配问题。
-
所有权转移
std::unique_ptr<int> ptr1(new int(30)); std::unique_ptr<int> ptr2 = std::move(ptr1); // 使用 std::move 转移所有权 std::cout << *ptr2 << std::endl; // 输出 30 // ptr1 现在为空,ptr2 指向对象
-
重置和释放
ptr2.reset(new int(40)); // 释放旧对象,指向新对象 std::cout << *ptr2 << std::endl; // 输出 40 ptr2.reset(); // 释放对象,ptr2 变为空
1.2 std::shared_ptr
std::shared_ptr
是一个共享所有权的智能指针,多个 shared_ptr
可以指向同一个对象,当最后一个 shared_ptr
被销毁时,对象才会被释放。
-
创建和初始化
#include <memory> #include <iostream> int main() { // 创建一个 shared_ptr std::shared_ptr<int> ptr1(new int(50)); std::cout << *ptr1 << std::endl; // 输出 50 // 使用 make_shared 创建 shared_ptr(推荐) auto ptr2 = std::make_shared<int>(60); std::cout << *ptr2 << std::endl; // 输出 60 }
-
共享所有权
std::shared_ptr<int> ptr1(new int(70)); std::shared_ptr<int> ptr2 = ptr1; // ptr2 和 ptr1 共享同一个对象 std::cout << *ptr2 << std::endl; // 输出 70
-
引用计数
std::shared_ptr<int> ptr1(new int(80)); std::shared_ptr<int> ptr2 = ptr1; std::cout << ptr1.use_count() << std::endl; // 输出 2
-
弱指针
std::weak_ptr
是一个弱引用,它允许访问shared_ptr
指向的对象,但不会增加引用计数。std::shared_ptr<int> ptr1(new int(90)); std::weak_ptr<int> weakPtr = ptr1; if (auto sharedPtr = weakPtr.lock()) { // 检查对象是否仍然存在 std::cout << *sharedPtr << std::endl; // 输出 90 } else { std::cout << "Object has been destroyed" << std::endl; }
1.3 std::weak_ptr
std::weak_ptr
是一个弱引用,它允许访问 shared_ptr
指向的对象,但不会增加引用计数。
- 创建和使用
std::shared_ptr<int> sharedPtr(new int(100)); std::weak_ptr<int> weakPtr(sharedPtr); if (auto lockedPtr = weakPtr.lock()) { std::cout << *lockedPtr << std::endl; // 输出 100 } else { std::cout << "Object has been destroyed" << std::endl; }
2. 内存分配器
<memory>
库还提供了内存分配器的功能,用于自定义内存分配策略。
2.1 std::allocator
std::allocator
是一个简单的内存分配器模板类,用于分配和释放内存。
- 使用示例
#include <memory> #include <iostream> int main() { std::allocator<int> alloc; int* ptr = alloc.allocate(5); // 分配内存,但不初始化 alloc.construct(ptr, 1); // 构造对象 alloc.construct(ptr + 1, 2); alloc.construct(ptr + 2, 3); alloc.construct(ptr + 3, 4); alloc.construct(ptr + 4, 5); for (int i = 0; i < 5; ++i) { std::cout << ptr[i] << " "; // 输出 1 2 3 4 5 } std::cout << std::endl; alloc.destroy(ptr + 4); // 销毁对象 alloc.destroy(ptr + 3); alloc.destroy(ptr + 2); alloc.destroy(ptr + 1); alloc.destroy(ptr); alloc.deallocate(ptr, 5); // 释放内存 }
2.2 自定义分配器
可以自定义内存分配器,以满足特定需求。
- 自定义分配器示例
#include <memory> #include <iostream> template <typename T> class MyAllocator { public: using value_type = T; MyAllocator() = default; template <typename U> MyAllocator(const MyAllocator<U>&) {} T* allocate(std::size_t n) { std::cout << "Allocating " << n << " elements" << std::endl; return static_cast<T*>(::operator new(n * sizeof(T))); } void deallocate(T* p, std::size_t n) { std::cout << "Deallocating " << n << " elements" << std::endl; ::operator delete(p); } }; int main() { std::vector<int, MyAllocator<int>> vec(5); for (int i = 0; i < 5; ++i) { vec[i] = i + 1; } for (int i = 0; i < 5; ++i) { std::cout << vec[i] << " "; // 输出 1 2 3 4 5 } std::cout << std::endl; }
3. 其他功能
<memory>
库还提供了一些辅助功能,例如 std::allocate_shared
和 std::allocate_unique
。
3.1 std::allocate_shared
std::allocate_shared
是一个函数模板,用于使用自定义分配器创建 shared_ptr
。
- 使用示例
#include <memory> #include <iostream> int main() { std::shared_ptr<int> ptr = std::allocate_shared<int>(std::allocator<int>(), 123); std::cout << *ptr << std::endl; // 输出 123 }
3.2 std::allocate_unique
std::allocate_unique
是一个函数模板,用于使用自定义分配器创建 unique_ptr
。
- 使用示例
#include <memory> #include <iostream> int main() { std::unique_ptr<int> ptr = std::allocate_unique<int>(std::allocator<int>(), 456); std::cout << *ptr << std::endl; // 输出 456 }
4. 总结
<memory>
库是 C++ 标准库中用于内存管理的重要工具。它提供了智能指针(如 std::unique_ptr
和 std::shared_ptr
)、内存分配器(如 std::allocator
),以及相关的辅助功能。通过使用这些工具,可以更安全、高效地管理动态内存,避免常见的内存管理错误。
5. 注意事项
-
智能指针的使用
- 避免在智能指针之间直接使用
new
和delete
,而是使用std::make_unique
和std::make_shared
。 - 注意
std::unique_ptr
的所有权转移特性,避免误用。 - 使用
std::weak_ptr
时,需要检查对象是否仍然存在。
- 避免在智能指针之间直接使用
-
自定义分配器
- 自定义分配器需要满足分配器的要求,包括
allocate
和deallocate
方法。 - 自定义分配器可以用于优化内存分配性能,但需要谨慎设计。
- 自定义分配器需要满足分配器的要求,包括
-
性能
std::shared_ptr
的引用计数可能会带来一定的性能开销,但在大多数情况下是可以接受的。- 如果对性能有极高要求,可以考虑使用
std::unique_ptr
或自定义分配器。
通过合理使用 <memory>
库的功能,可以显著提高 C++ 程序的内存管理效率和安全性。