当auto_ptr_ref真的有必要时,你能举个例子吗?

时间:2011-06-07 13:36:14

标签: c++

我想更好地理解创建库背后的机制和问题,我决定从std :: auto_ptr开始。 我熟悉语法和用法,但我试图了解实现细节。我已经实现了我的auto_ptr版本,它看起来像这样:

#ifndef _AUTO_PTR_H
#define _AUTO_PTR_H

namespace test
{    
    template<typename T>
    class auto_ptr
    {
        public:
            //ctor, dtor, copy ctor and assignment
            explicit auto_ptr(T* ptr = 0) throw() 
                : ptr_(ptr) {}

            auto_ptr(auto_ptr& other) throw()
                :ptr_(other.release()) {}

            auto_ptr<T>& operator=(auto_ptr<T>& other)
            {
                reset(other.release());
                return *this;
            }

            template<typename U>
            auto_ptr<T>& operator=(auto_ptr<U>& other) throw()
            {
                reset(other.release());
                return *this;
            }

            template<typename U>
            auto_ptr(auto_ptr<U>& other) throw() 
                : ptr_(other.release()) {}

            //member
            ~auto_ptr() throw() { delete ptr_; }

            T& operator*() const throw() { return *ptr_; }

            T* operator->() const throw() { return ptr_; }

            T* get() const throw() { return ptr_; }         

            T* release() throw()
            { 
                T* temp = ptr_;
                ptr_ = 0;
                return temp;
            }

            void reset(T* ptr = 0) throw()
            {
                if (ptr_ != ptr)
                {
                    delete ptr_;
                    ptr_ = ptr;
                }
            }

        private:
            T* ptr_;
    };
}

#endif

我的班级正在完成这项工作,然后我阅读了this question,很明显为什么要使用auto_ptr_ref。但是,如果不添加auto_ptr_ref,auto_ptr的行为会有所不同,我想有一个实际的例子。

我的实现可以正常使用这些功能:

template <typename T>
test::auto_ptr<T> source()
{
    return test::auto_ptr<T>(new T());
}

template <typename T>
void sink(test::auto_ptr<T> bye)
{
}

template <typename T>
void useButNotSink(const test::auto_ptr<T> seeYouLater)
{
    std::cout << *seeYouLater << std::endl;
}

使用此测试程序:

test::auto_ptr<double> copyConstructed(source<double>());

std::cout << *copyConstructed << std::endl;
std::cout << copyConstructed.get() << std::endl;

test::auto_ptr<double> assigned(new double(10));
assigned = source<double>();

std::cout << *assigned << std::endl;
std::cout << assigned.get() << std::endl;
*assigned = 2044;

std::cout << *assigned << std::endl;
useButNotSink(assigned);
sink(assigned);
std::cout << assigned.get() << std::endl;

我确定我遗漏了一些东西,你能给我一个例子,其中auto_ptr_ref结构和转换运算符是必须的,以获得正确的行为吗?

由于

2 个答案:

答案 0 :(得分:4)

您似乎正在使用编译器扩展。我没有看到带有const引用参数的复制构造函数。由于您无法将临时传递给非const引用,

test::auto_ptr<double> copyConstructed(source<double>());

应该无法编译(source<double>()的结果是临时的)。

(请注意,在C ++ 0X中,右值参考是获得效果的更好方法。)

答案 1 :(得分:4)

你的第一行

test::auto_ptr<double> copyConstructed(source<double>());

已经被任何符合标准的编译器无法编译。启用C ++语言扩展时,MSVC将允许它。禁用扩展程序,您将立即意识到需要auto_ptr_ref

auto_ptr_ref背后的机制对于MSVC 6.0来说过于复杂,所以为了支持编译器必须依赖于此编译器扩展的完整std::auto_ptr功能的一些相似性,即允许非const引用被绑定到临时对象。该问题已在更高版本的编译器中得到修复,但此编译器扩展在默认情况下仍保持启用状态。