如何实现smart_ptr

前面文章已经介绍了如何实现一个简单的引用对象,在这里我将使用这个简单的引用计数对象来实现smart_ptr,这个对于我们日后对象指针在容器中的使用是相当的方便的,希望能给网友带来一些启迪。对于指针的析构器,请参考: http://blog.youkuaiyun.com/hello_wyq/archive/2006/07/07/888743.aspx
// Author    : Wang yanqing
// Module    : Smart pointer
// Version    : 0.01
// Date        : 03-Aug-2005
// Reversion:
// Date        :
// EMail    : hello.wyq@gmail.com
#ifndef _SMART_PTR_H
#define _SMART_PTR_H

#include <memory>

#include "inc/smart_ptr_deleter.h"
#include "inc/smart_ptr_refcnt_obj.h"

template < typename T, typename U = SmartPtrDeleter<T> >
class SmartPtr
{
    RefCntObj<T, U>        ref;

public:   
    explicit SmartPtr( T *pt, const U &u = U() )
        : ref( pt, u )
    {
        assert( pt != NULL );
    }

    template <typename Y>
    explicit SmartPtr( std::auto_ptr<Y> & rhs, const U &u = U() )
        : ref( rhs.get(), u )
    {
        assert( rhs.get() != NULL );
        rhs.release();
    }

    inline T* operator ->() const
    {
        return ref.get();
    }

    inline T& operator *() const
    {
        return *ref.get();
    }

    inline bool operator !() const
    {
        return ref.get() == NULL;
    }

    template <typename Y, typename D>
    inline bool operator ==( const SmartPtr<Y, D> &rhs ) const
    {
        return this == &rhs || ref.get() == rhs.ref.get();
    }

    template <typename Y, typename D>
    inline bool operator !=( const SmartPtr<Y, D> &rhs ) const
    {
        return !(this == &rhs || ref.get() == rhs.ref.get());
    }

    template <typename Y, typename D>
    inline bool operator <( const SmartPtr<Y, D> &rhs ) const
    {
        return ref.get() < rhs.ref.get();
    }

    template <typename Y, typename D>
    inline bool operator >( const SmartPtr<Y, D> &rhs ) const
    {
        return ref.get() > rhs.ref.get();
    }

    template <typename Y, typename D>
    inline void swap( SmartPtr<Y, D> &rhs )
    {
        if ( this == &rhs )
            return;
       
        ref.swap( rhs.ref );
    }
};

#endif
 
<think>好的,我现在需要解释用户提供的C++代码行:std::unique_ptr<UserData> smart_ptr = std::make_unique<UserData>();。首先,我得确定用户对智能指针的了解程度。可能用户是刚开始学习C++,或者已经有一定基础但想确认理解是否正确。 首先,我应该分解这段代码的各个部分。std::unique_ptr是一个智能指针模板类,用于管理动态分配的对象,确保自动释放内存,避免泄漏。UserData是用户自定义的数据类型,这里作为模板参数传递给unique_ptr。std::make_unique是C++14引入的工厂函数,用于创建unique_ptr实例,比直接使用new更安全,因为能避免显式的new和delete,减少异常导致的内存泄漏风险。 接下来,需要解释这行代码的整体作用:创建了一个名为smart_ptr的unique_ptr,指向一个动态分配的UserData对象。这里要强调unique_ptr的所有权独占特性,即同一时间只能有一个unique_ptr拥有该对象的所有权,当smart_ptr离开作用域时,会自动删除UserData对象,释放内存。 然后,可能需要对比旧式的裸指针用法,说明智能指针的优势,比如自动内存管理、异常安全等。同时,可以提到std::make_unique的优点,比如代码更简洁、类型安全,并且因为分配内存和构造对象一次性完成,可能更高效,也避免了潜在的内存泄漏问题,比如如果在new之后但在赋值给unique_ptr之前发生异常,就会泄漏,而make_unique避免了这种情况。 用户可能存在的疑问包括:unique_ptr能否被复制?答案是不能,只能移动,这符合独占所有权的语义。或者如何传递unique_ptr给函数?可以通过引用,或者使用移动语义转移所有权。另外,可能需要注意UserData的构造参数是否需要传递到make_unique中,比如如果UserData有构造函数参数,应该放在make_unique的参数列表里。 此外,可能需要提到C++11中如果没有make_unique的情况,用户需要直接使用new,然后将其赋给unique_ptr,例如:std::unique_ptr<UserData> smart_ptr(new UserData());,但在C++14之后推荐使用make_unique。 最后,是否需要给出示例代码,比如使用智能指针后的析构自动调用,或者如何转移所有权,比如使用std::move,或者如何访问指针指向的对象,使用get()方法或operator->等。 需要确保解释清晰,避免技术术语过于晦涩,同时涵盖关键点,如内存管理、所有权、异常安全、make_unique的好处等。同时,检查是否有遗漏的部分,比如自定义删除器的可能性,但在这个例子中可能不涉及,所以可以暂时不提,除非用户后续提问。</think>以下是对代码 `std::unique_ptr<UserData> smart_ptr = std::make_unique<UserData>();` 的分步解析: --- ### **1. 代码功能** - 创建一个**智能指针** `smart_ptr`,指向动态分配的 `UserData` 类型对象 - 通过 `std::make_unique` 实现内存分配与对象构造的**原子化操作** - 确保对象生命周期结束时**自动释放内存**,避免内存泄漏 --- ### **2. 核心组件解析** #### **(1) `std::unique_ptr`** - **特性**: ✅ 独占所有权(不可复制,只能移动) ✅ 零额外内存开销(与裸指针大小相同) ✅ 支持自定义删除器(默认使用 `delete`) - **内存安全示例**: ```cpp { auto ptr = std::make_unique<UserData>(); // 进入作用域时构造 ptr->process(); // 使用对象 } // 离开作用域时自动调用 ~UserData() 并释放内存 ``` #### **(2) `std::make_unique`** - **优势对比**: | 方式 | 异常安全性 | 代码简洁性 | 构造效率 | |-----------------------|------------|------------|----------| | `new` + 构造函数 | ❌ 可能泄漏 | 冗余 | 低 | | `std::make_unique` | ✅ 安全 | 简洁 | 高 | - **底层等价代码**: ```cpp // std::make_unique<UserData>() 等效于: std::unique_ptr<UserData>(new UserData()); ``` --- ### **3. 关键操作** #### **(1) 访问对象** ```cpp // 方式1:箭头操作符 smart_ptr->member_function(); // 方式2:解引用 (*smart_ptr).data_field = 42; // 方式3:获取原始指针(慎用!) UserData* raw_ptr = smart_ptr.get(); ``` #### **(2) 所有权转移** ```cpp // 通过 std::move 转移所有权 std::unique_ptr<UserData> new_owner = std::move(smart_ptr); // 转移后原指针变为 nullptr assert(smart_ptr == nullptr); ``` #### **(3) 重置资源** ```cpp // 释放当前对象并置空 smart_ptr.reset(); // 释放当前对象并接管新对象 smart_ptr.reset(new UserData()); ``` --- ### **4. 典型应用场景** | 场景 | 代码示例 | 优势体现 | |---------------------|----------------------------------------|------------------------------| | **工厂模式** | `Factory::create()` 返回 `unique_ptr` | 明确所有权传递 | | **多态对象管理** | `unique_ptr<Base> p = make_unique<Derived>()` | 自动正确调用派生类析构函数 | | **容器存储对象** | `vector<unique_ptr<UserData>>` | 容器元素具备独立生命周期管理 | --- ### **5. 与裸指针对比分析** ```cpp // 危险示例:裸指针易导致内存泄漏 void unsafe_code() { UserData* raw_ptr = new UserData(); if (some_error) throw std::runtime_error("Oops"); // 此处发生异常 → 内存泄漏! delete raw_ptr; // 正常流程才会执行 } // 安全示例:智能指针保证资源释放 void safe_code() { auto smart_ptr = std::make_unique<UserData>(); if (some_error) throw std::runtime_error("Safe"); // 即使抛出异常,smart_ptr 仍会自动释放内存 } ``` --- 是否需要进一步了解以下内容? - 如何为 `unique_ptr` 实现自定义删除器(如用于文件句柄或网络连接) - `unique_ptr` 在异常安全机制中的具体表现 - 与 `shared_ptr` 的性能差异及适用场景选择
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值