scoped_ptr 与 auto_ptr 与 shared_ptr 区别总结

1.auto_ptr 被复制后,将失去原来所致资源的所有权;
2.scoped_ptr永远不能被复制或被赋值!scoped_ptr拥有它所指向的资源的所有权,并永远不会放弃这个所有权;
3.shared_ptr 是可以共享所有权的智能指针;


#include "stdafx.h"
//#include "windows.h"
#include <memory>
#include <iostream>
using std::tr1::shared_ptr;
class Foo
{
public:
Foo()
{
std::cout<<"new Foo()"<<std::endl;
i = 0;
}
~Foo()
{
std::cout<<"destroy Foo()"<<std::endl;
}
void print()
{
std::cout<<"Foo::print"<<std::endl;
}
int i;
};

void OutSharePtr(shared_ptr<Foo> &P)
{
Foo* p = new Foo();
shared_ptr<Foo> sp1(p);
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
shared_ptr<Foo> sp2(sp1);
p->print();
sp2->print();
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
P = sp2;
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
}
void InSharePtr(shared_ptr<Foo> &p)
{
p->i += 100;
std::cout<<p.use_count()<<"::"<<p.get()<<std::endl;
}
#include <algorithm>
char upCase(char c)
{
return toupper(c);
}
int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<Foo> sp1(new Foo());
shared_ptr<Foo> sp2(sp1);
shared_ptr<Foo> sp3;
sp1->print();
sp2->print();
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
std::cout<<sp3.use_count()<<"::"<<sp3.get()<<std::endl;
sp3.swap(sp1);
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
std::cout<<sp3.use_count()<<"::"<<sp3.get()<<std::endl;
sp3.reset();
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
sp2.reset();
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
sp1.reset();
std::cout<<sp1.use_count()<<"::"<<sp1.get()<<std::endl;
return 0;
}

C++11 引入的智能指针通过自动管理动态内存,显著提升了代码的安全性和可维护性。以下是它们的核心内容:


一、智能指针的优点

  1. 自动内存管理
    智能指针在作用域结束时自动释放内存,避免手动 delete 导致的内存泄漏。
  2. 异常安全
    即使发生异常,资源也会被正确释放,符合 RAII(资源获取即初始化)原则。
  3. 明确的资源所有权
    通过所有权模型(独占、共享)清晰表达资源生命周期。
  4. 更安全的指针操作
    禁止隐式类型转换,减少野指针和空指针解引用风险。

二、智能指针的种类

1. std::unique_ptr
  • 特点:独占所有权,不可复制,只能移动(通过 std::move 转移所有权)。
  • 适用场景:单一所有者,如工厂函数返回对象、局部资源管理。
  • 优势:无额外开销,轻量高效。
  • 示例
     

    cpp

    复制

    std::unique_ptr<int> ptr = std::make_unique<int>(42); // C++14+ 推荐
    // 或
    std::unique_ptr<int> ptr(new int(42));
2. std::shared_ptr
  • 特点:共享所有权,通过引用计数管理资源,支持复制。
  • 适用场景:多个对象需共享同一资源(如容器、多线程共享数据)。
  • 注意:循环引用会导致内存泄漏,需配合 weak_ptr 解决。
  • 优势:灵活共享资源,自动释放。
  • 示例
     

    cpp

    复制

    std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
    std::shared_ptr<int> ptr2 = ptr1; // 引用计数 +1
3. std::weak_ptr
  • 特点:非拥有性观察者,不增加引用计数,需通过 lock() 获取临时 shared_ptr
  • 适用场景:打破 shared_ptr 循环引用(如双向链表、缓存)。
  • 优势:解决内存泄漏问题,避免所有权混乱。
  • 示例
     

    cpp

    复制

    std::shared_ptr<int> shared = std::make_shared<int>(42);
    std::weak_ptr<int> weak = shared;
    if (auto tmp = weak.lock()) { // 尝试获取 shared_ptr
        // 使用 tmp 访问资源
    }

三、关键注意事项

  1. 优先使用 std::make_unique 和 std::make_shared
    • 更高效(make_shared 合并内存分配),避免异常安全问题。
  2. 避免原始指针的混用
    • 智能指针应直接管理资源,避免与 new/delete 手动操作交叉使用。
  3. 循环引用问题
    • 当两个 shared_ptr 互相引用时,需将其中一个改为 weak_ptr

四、总结

  • ​**unique_ptr**:独占资源,轻量高效。
  • ​**shared_ptr**:共享资源,需警惕循环引用。
  • ​**weak_ptr**:辅助 shared_ptr,解决循环引用。

合理使用智能指针可大幅减少内存管理错误,是现代 C++必备工具。


auto_ptr 和 scoped_ptr 是否属于 C++11?

  1. auto_ptr

    • C++98 标准auto_ptr 是 C++98 标准中引入的早期智能指针,用于管理动态内存。
    • C++11 中的状态:在 C++11 中被标记为 ​已废弃(deprecated)​,并在 C++17 中正式移除。
    • 原因:设计存在严重缺陷(如所有权转移的隐式行为),容易导致代码错误。
  2. scoped_ptr

    • 非标准库组件scoped_ptr 并非 C++ 标准库的一部分,而是 ​Boost 库 中的一个智能指针(定义在 <boost/scoped_ptr.hpp> 中)。
    • C++11 中的状态:C++11 未引入此名称的智能指针,但功能类似的 unique_ptr 被纳入标准库。
    • 特点:不可复制、不可移动,仅在作用域内有效,自动释放资源。

与 C++11 智能指针的区别

1. auto_ptr vs unique_ptr
特性auto_ptr (C++98)unique_ptr (C++11)
所有权模型独占所有权,但通过隐式拷贝语义转移所有权。独占所有权,​禁止隐式拷贝,必须显式使用 std::move转移所有权。
拷贝行为拷贝时会将原指针置为 nullptr,可能导致悬空指针。拷贝构造函数和赋值运算符被删除,无法拷贝。
移动语义无移动语义(C++11 前)。支持移动语义(通过 std::move)。
安全性易导致意外的所有权转移和内存泄漏。更安全,所有权转移显式且无歧义。
适用场景C++98 代码,已过时。现代 C++ 中替代 auto_ptr

示例对比

 

cpp

复制

// auto_ptr(危险!)
auto_ptr<int> p1(new int(42));
auto_ptr<int> p2 = p1;  // p1 变为 nullptr,p2 接管资源!
int* raw = p1.get();    // 返回 nullptr,解引用会导致崩溃!

// unique_ptr(安全)
unique_ptr<int> up1(new int(42));
unique_ptr<int> up2 = move(up1);  // 显式转移所有权,up1 变为 nullptr
int* raw = up1.get();             // 返回 nullptr,但行为明确

2. scoped_ptr vs unique_ptr
特性scoped_ptr (Boost)unique_ptr (C++11)
标准库支持非标准(Boost 库)。C++11 标准的一部分。
拷贝/移动语义不可拷贝、不可移动。不可拷贝,但支持移动语义。
灵活性仅限作用域内使用,无法转移所有权。支持通过 std::move 转移所有权。
功能扩展性功能简单,无自定义删除器等高级特性。支持自定义删除器、数组类型等。
内存开销无额外开销。无额外开销,与 scoped_ptr 类似。

核心区别

  • scoped_ptr 是 Boost 提供的轻量级工具,适用于严格作用域内的资源管理,但无法转移所有权。
  • unique_ptr 是 C++11 标准,功能更强大(支持移动语义、自定义删除器),是现代 C++ 的首选。

总结:为何 C++11 智能指针更优?

  1. 明确的 ownership 语义
    • unique_ptr 通过禁止隐式拷贝、支持显式移动,彻底解决了 auto_ptr 的所有权混乱问题。
  2. 异常安全与 RAII
    • C++11 智能指针严格遵循 RAII,与异常安全无缝结合。
  3. 功能扩展性
    • 支持自定义删除器(如文件句柄、锁)、数组类型(unique_ptr<T[]>)等。
  4. 标准库支持
    • unique_ptr 和 shared_ptr 是 C++11 标准的一部分,兼容性和可移植性更强。

何时使用旧智能指针?

  • ​**auto_ptr**:仅在维护遗留 C++98 代码时可能遇到,应尽快迁移到 unique_ptr
  • ​**scoped_ptr**:如果项目已使用 Boost 库且无需移动语义,可继续使用,但新项目建议优先选择 unique_ptr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值