当auto_ptr_ref真的很必要时,你能给我举个例子吗

Can you give me an example when auto_ptr_ref is really necessary?

本文关键字:ref ptr auto 真的      更新时间:2023-10-16

我想更好地了解创建库背后的机制和问题,我决定从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

我的课已经完成了大部分的工作,然后我读了这个问题,很清楚为什么会有auto_ptr_ref。然而,我想举一个实际的例子,当auto_ptr在不添加auto_ptr_ref的情况下表现不同时。

我的实现可以正确地使用以下功能:

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结构和转换运算符是必需的,以获得正确的行为?

感谢

您的第一行

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

已不可由任何符合标准的编译器编译。当启用C++语言扩展时,MSVC将允许它。禁用扩展,您将立即意识到对auto_ptr_ref的需求。

auto_ptr_ref背后的机制对于MSVC 6.0来说太复杂了,因此为了支持std::auto_ptr功能的某些相似性,编译器必须依赖于此编译器扩展,即允许将非常量引用绑定到临时对象。该问题在编译器的后续版本中得到了修复,但该编译器扩展至今仍处于默认启用状态。

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

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

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

(注意,在C++0X中,右值引用是实现效果的更好方法)。