c++ memory

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_sharedstd::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_ptrstd::shared_ptr)、内存分配器(如 std::allocator),以及相关的辅助功能。通过使用这些工具,可以更安全、高效地管理动态内存,避免常见的内存管理错误。

5. 注意事项

  • 智能指针的使用

    • 避免在智能指针之间直接使用 newdelete,而是使用 std::make_uniquestd::make_shared
    • 注意 std::unique_ptr 的所有权转移特性,避免误用。
    • 使用 std::weak_ptr 时,需要检查对象是否仍然存在。
  • 自定义分配器

    • 自定义分配器需要满足分配器的要求,包括 allocatedeallocate 方法。
    • 自定义分配器可以用于优化内存分配性能,但需要谨慎设计。
  • 性能

    • std::shared_ptr 的引用计数可能会带来一定的性能开销,但在大多数情况下是可以接受的。
    • 如果对性能有极高要求,可以考虑使用 std::unique_ptr 或自定义分配器。

通过合理使用 <memory> 库的功能,可以显著提高 C++ 程序的内存管理效率和安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值