BOOST c++库学习 之 Smart Ptr库智能指针库入门实战指南 以及 使用boost.smartptr库以及使用普通指针且不释放内存的对比例程(需要实际运行,然后观察电脑内存的变化)

Boost.SmartPtr库是Boost库的一部分,专门用于提供各种类型的智能指针,以帮助开发者更安全、更有效地管理动态内存。智能指针的核心思想是通过自动化资源管理来减少内存泄漏、悬挂指针等常见问题,提升代码的安全性和可维护性。下面是对Boost.SmartPtr库的简要介绍以及它包含的主要API。

SmartPtr库简介

1. 自动内存管理

Boost.SmartPtr库通过引用计数、作用域管理等机制,实现了动态内存的自动管理。智能指针可以在超出作用域或不再需要时自动释放内存,避免手动管理可能引发的错误。

2. 多种智能指针类型

该库提供了多种类型的智能指针,包括共享所有权、独占所有权、弱引用、嵌入式引用计数等,满足不同的内存管理需求。

3. 与C++标准库兼容

Boost.SmartPtr库的设计与C++11及更高版本的标准库智能指针(如std::shared_ptrstd::unique_ptr等)兼容,使得从Boost智能指针迁移到标准库智能指针相对简单。

SmartPtr库中的主要API

1. boost::shared_ptr

shared_ptr 是一种引用计数型智能指针,多个shared_ptr可以共享同一个对象。当最后一个shared_ptr被销毁时,所管理的资源会自动释放。

使用方式

#include <boost/shared_ptr.hpp>
#include <iostream>

void example_shared_ptr() {
    boost::shared_ptr<int> sp1(new int(10));  // 创建 shared_ptr 管理 int 对象
    std::cout << "Value: " << *sp1 << std::endl;  // 输出:10

    boost::shared_ptr<int> sp2 = sp1;  // 复制 sp1 到 sp2,sp1 和 sp2 共享同一对象
    std::cout << "Reference count: " << sp1.use_count() << std::endl;  // 输出:2

    sp1.reset();  // 释放 sp1 对象,sp2 仍然拥有该对象
    std::cout << "Reference count after reset: " << sp2.use_count() << std::endl;  // 输出:1
}

2. boost::scoped_ptr

scoped_ptr 是一种不可复制的智能指针,只在其作用域内管理资源。它在作用域结束时自动释放资源。

使用方式

#include <boost/scoped_ptr.hpp>
#include <iostream>

void example_scoped_ptr() {
    boost::scoped_ptr<int> sp(new int(20));  // 创建 scoped_ptr 管理 int 对象
    std::cout << "Value: " << *sp << std::endl;  // 输出:20

    // sp2 = sp;  // 错误,scoped_ptr 不可复制

    sp.reset();  // 显式释放资源
    // std::cout << *sp << std::endl;  // 此时访问 sp 是未定义行为
}

3. boost::weak_ptr

weak_ptr 是一种弱引用指针,与shared_ptr配合使用,不增加引用计数。主要用于防止循环引用。

使用方式

#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <iostream>

void example_weak_ptr() {
    boost::shared_ptr<int> sp(new int(30));  // 创建 shared_ptr
    boost::weak_ptr<int> wp(sp);  // 创建 weak_ptr 指向 shared_ptr 管理的对象

    if (auto sp2 = wp.lock()) {  // 尝试提升 weak_ptr 到 shared_ptr
        std::cout << "Value: " << *sp2 << std::endl;  // 输出:30
    } else {
        std::cout << "Object has been deleted." << std::endl;
    }

    sp.reset();  // 销毁 shared_ptr,释放对象

    if (auto sp2 = wp.lock()) {  // 此时提升失败
        std::cout << "Value: " << *sp2 << std::endl;
    } else {
        std::cout << "Object has been deleted." << std::endl;  // 输出
    }
}

4. boost::intrusive_ptr

intrusive_ptr 需要用户自己管理对象的引用计数,它不存储额外的数据结构,适用于性能要求较高的场合。

使用方式

#include <boost/intrusive_ptr.hpp>
#include <iostream>

class MyClass {
private:
    int ref_count = 0;
public:
    void add_ref() { ++ref_count; }
    void release() { if (--ref_count == 0) delete this; }
    void display() { std::cout << "MyClass object" << std::endl; }
};

// 必须为 intrusive_ptr 提供这两个全局函数
void intrusive_ptr_add_ref(MyClass* p) { p->add_ref(); }
void intrusive_ptr_release(MyClass* p) { p->release(); }

void example_intrusive_ptr() {
    boost::intrusive_ptr<MyClass> ip(new MyClass);  // 创建 intrusive_ptr
    ip->display();  // 使用指针访问对象的方法
}

5. boost::unique_ptr

unique_ptr 是独占所有权智能指针,确保在任何时刻只有一个指针拥有该资源。它通过移动语义转移所有权,不能复制。

使用方式

#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
#include <iostream>

void example_unique_ptr() {
    boost::interprocess::unique_ptr<int> up(new int(40));  // 创建 unique_ptr
    std::cout << "Value: " << *up << std::endl;  // 输出:40

    boost::interprocess::unique_ptr<int> up2 = std::move(up);  // 移动所有权
    std::cout << "Value after move: " << *up2 << std::endl;  // 输出:40

    // up 已经不再拥有资源
}

6. boost::make_sharedboost::allocate_shared:这些辅助函数用于创建shared_ptr实例,更高效地分配内存,减少额外的内存分配操作。

使用方式

#include <boost/make_shared.hpp>
#include <iostream>

void example_make_shared() {
    auto sp = boost::make_shared<int>(50);  // 使用 make_shared 创建 shared_ptr
    std::cout << "Value: " << *sp << std::endl;  // 输出:50
}

void example_allocate_shared() {
    std::allocator<int> alloc;
    auto sp = boost::allocate_shared<int>(alloc, 60);  // 使用 allocate_shared 创建 shared_ptr
    std::cout << "Value: " << *sp << std::endl;  // 输出:60
}

使用boost.smartptr库以及使用普通指针且不释放内存的对比例程

为了展示 Boost.SmartPtr 智能指针的优势,我们将生成两个测试程序,一个使用 Boost.SmartPtr 的智能指针API,另一个手动管理内存并故意引入内存泄漏。我们将通过比较它们在内存管理上的简洁性和安全性,以及运行时间的对比来体现智能指针的优势。

程序一:使用 Boost.SmartPtr 的程序

代码

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
#include <vector>
#include <chrono>

void using_boost_smart_ptr() {
    auto start = std::chrono::high_resolution_clock::now();

    std::vector<boost::shared_ptr<int>> vec;
    for (int i = 0; i < 1000000; ++i) {
        vec.push_back(boost::make_shared<int>(i));  // 使用 shared_ptr 管理内存
    }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = end - start;

    std::cout << "Time taken with Boost.SmartPtr: " << elapsed.count() << " seconds" << std::endl;
}

int main() {
    using_boost_smart_ptr();
    return 0;
}

操作步骤

  1. 安装 Boost 库(如果尚未安装)。
  2. 使用以下命令编译程序(假设文件名为 smart_ptr_example.cpp):
    g++ -o smart_ptr_example smart_ptr_example.cpp -lboost_system
    
  3. 运行编译后的程序:
    ./smart_ptr_example
    

执行结果

Time taken with Boost.SmartPtr: [X.XXXX] seconds

程序二:不使用智能指针的程序(引入内存泄漏)

代码

#include <iostream>
#include <vector>
#include <chrono>

void not_using_smart_ptr() {
    auto start = std::chrono::high_resolution_clock::now();

    std::vector<int*> vec;
    for (int i = 0; i < 1000000; ++i) {
        vec.push_back(new int(i));  // 手动分配内存
    }

    // 故意引入内存泄漏:未释放内存
    // for (int* ptr : vec) {
    //     delete ptr;
    // }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = end - start;

    std::cout << "Time taken without Boost.SmartPtr (with leak): " << elapsed.count() << " seconds" << std::endl;
}

int main() {
    not_using_smart_ptr();
    return 0;
}

操作步骤

  1. 编译程序(假设文件名为 no_smart_ptr_example.cpp):
    g++ -o no_smart_ptr_example no_smart_ptr_example.cpp
    
  2. 运行编译后的程序:
    ./no_smart_ptr_example
    

执行结果

Time taken without Boost.SmartPtr (with leak): [Y.YYYY] seconds

智能指针 vs 普通指针的优势对比

1. 内存管理自动化

  • 智能指针:智能指针自动管理资源的释放,避免了手动调用delete,从而大大减少了内存泄漏的可能性。特别是shared_ptrscoped_ptr等智能指针,能够自动在资源不再使用时释放资源。
  • 普通指针:普通指针需要开发者手动管理内存释放。手动管理容易出错,导致内存泄漏或者二次释放(double free)等问题。

2. 避免悬挂指针

  • 智能指针:智能指针保证了对象的生命周期。如果一个对象仍然被一个智能指针引用,那么它就不会被释放,从而避免了悬挂指针问题。
  • 普通指针:普通指针指向的对象可能被意外释放,导致悬挂指针问题。如果程序试图访问一个悬挂指针,可能会导致未定义行为和程序崩溃。

3. 防止循环引用

  • 智能指针:使用shared_ptrweak_ptr组合可以有效防止循环引用问题。weak_ptr不会增加引用计数,打破了循环引用,避免了资源泄漏。
  • 普通指针:在复杂的对象图中,循环引用问题很难被检测和解决,容易导致内存泄漏。

4. 线程安全

  • 智能指针shared_ptr 的引用计数操作是线程安全的,这在多线程环境中特别有用。多个线程可以安全地共享同一个shared_ptr对象。
  • 普通指针:普通指针在多线程环境下不具备任何线程安全的特性。共享普通指针对象时需要开发者自己管理并发问题,容易出错。

5. 所有权管理

  • 智能指针unique_ptr等智能指针通过移动语义明确了对象的所有权,防止对象被多个指针管理,导致不明确的所有权和资源释放问题。
  • 普通指针:普通指针没有所有权的概念,容易导致对象所有权的不确定性,进而引发资源管理的问题。

6. 代码简洁性

  • 智能指针:智能指针简化了内存管理的代码,使得代码更加简洁和易于维护。例如,scoped_ptr会在超出作用域时自动释放资源,不需要手动调用delete
  • 普通指针:普通指针需要显式的内存管理代码,增加了代码的复杂性和维护成本。

总结

Boost库中的智能指针提供了相较于普通指针更安全、更高效的内存管理方案。它们自动化的内存管理、生命周期控制、线程安全特性等显著减少了内存泄漏、悬挂指针、循环引用等常见问题,使得C++开发更加健壮和高效。因此,推荐在C++编程中尽量使用智能指针代替普通指针,特别是在管理动态分配的资源时。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值