我写了一个名为auto_ptr的类,请帮忙检查代码

时间:2013-08-14 13:39:36

标签: c++

我只是想练习我的C ++代码,所以我自己实现了auto_ptr bi,我不知道我的代码中是否有任何错误。

#include <iostream>
#include <cassert>
using namespace std;

template <typename T>
class auto_ptr
{
public:
    explicit auto_ptr(T* p = NULL):m_p(p){}
    auto_ptr(auto_ptr& other);
    auto_ptr& operator=(auto_ptr& other);
    T* get() const { return m_p; }
    void reset(T* p = NULL);
    T& operator * (){ return *m_p; }
    T* operator -> (){ return m_p; }
    ~auto_ptr()
    {
        if(m_p)
            delete m_p;
        m_p = NULL;
    }   
private:
    T* m_p;
    T* release();
};


int main()
{
    auto_ptr<int> p(new int(3));
    cout<<*p<<endl;

    int *b = new int(6);
    p.reset(b);
    cout<<*p.get()<<endl;

    auto_ptr<int> p1(new int(10));
    p = p1;
    cout<<*p<<endl;
    assert(NULL == p1.get());

    auto_ptr<int> p2(new int(100));
    auto_ptr<int>p3(p2);
    cout<<*p3<<endl;
    assert(NULL == p2.get());
}



template <typename T>
T* auto_ptr<T>::release()
{
    T* temp = this->m_p;
    this->m_p = NULL;
    return temp;
}

template <typename T>
auto_ptr<T>::auto_ptr(auto_ptr& other)
{
    m_p = other.release();
}

template <typename T>
auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr& other)
{   
    if(this == &other)
        return *this;
    delete m_p;
    m_p = other.release();
    return *this;
}

template <typename T>
void auto_ptr<T>::reset(T* p)
{
    if(m_p != p)
    {
        delete m_p;
        m_p = p;    
    }
}   

但是我已经在STL here中看到了源代码。 我不知道为什么需要实现这些功能:

auto_ptr(auto_ptr_ref<_Tp> __ref) __STL_NOTHROW
: _M_ptr(__ref._M_ptr) {}

auto_ptr& operator=(auto_ptr_ref<_Tp> __ref) __STL_NOTHROW {
if (__ref._M_ptr != this->get()) {
  delete _M_ptr;
  _M_ptr = __ref._M_ptr;
}
return *this;
}

大家好,我明白了: 此函数用于将auto_ptr转换为auto_ptr_ref

    template<class Y>
    operator auto_ptr_ref<Y>() throw() {
        return auto_ptr_ref<Y>(release());
    }

2 个答案:

答案 0 :(得分:1)

  

我不知道我的代码中是否有任何错误。

我没有看到任何明显的错误;但是代码审查对于这个网站来说是偏离主题的。

  

我不知道为什么需要实现这些功能

auto_ptr_ref是一个奇怪的黑客,允许临时auto_ptr传递给函数或从函数返回。没有它,以下将无法编译:

void f(auto_ptr<int>);
f(auto_ptr<int>());

这里,函数调用尝试通过复制临时构造函数参数。但是,复制构造函数采用非const引用,因此无法在临时引用。

auto_ptr_ref之间添加隐式转换允许将临时转换为该类型,并从转换后的值初始化函数参数。该构造函数通过值获取其参数,因此使用临时值没有问题。

一种可能的实现(由C ++标准建议)是auto_ptr_ref只包含对auto_ptr的引用,转换构造函数和赋值运算符对该指针执行复制构造函数和赋值运算符的操作做他们的论点。看起来您正在查看的实现存储原始指针,在创建auto_ptr时从auto_ptr_ref释放它,并使用它来初始化新的auto_ptr

auto_ptr是一个有趣的历史教训,它讲述了如何在成为语言的一部分之前,以一种黑客和容易出错的方式模仿移动语义。但是,如果您有兴趣了解实际的现代C ++是如何工作的,那么最好忘记它并学习如何实现unique_ptr。这使用真实,安全的移动语义来完成auto_ptr没有取得成功的工作。

答案 1 :(得分:0)

尽管这个问题已经得到了很多支持,但我认为将Nicolai Josuttis' article about auto_ptr and auto_ptr_ref指向解释auto_ptr_ref的作用可能是个好主意:

  

普通的复制构造函数可以复制rvalue,但为了这样做,它必须将其参数声明为对const对象的引用。要使用普通的构造函数来复制auto_ptr,我们必须声明包含真实指针的数据成员是可变的,以便可以在复制构造函数中修改它。但是,这将允许您编写复制实际声明为const的auto_ptr对象的代码,将其所有权与其常量状态相矛盾。

     

另一种方法是找到一种机制,使rvalue能够转换为左值。引用类型的简单操作符转换函数不起作用,因为从不调用操作符转换函数将对象转换为自己的类型(请记住引用属性不是类型的一部分)。因此,引入了auto_ptr_ref类来提供这种转换为左值的机制。该机制依赖于重载和模板参数推导规则之间的细微差别。这种差异太微妙,无法用作通用编程工具,但足以使auto_ptr类正常工作。