Can you give me an example when auto_ptr_ref is really necessary?
I would like to understand better the mechanics and the issues behind creating library and I have decided to start from the std::auto_ptr. I am familiar with the syntax and the usage, however I am trying to understand the i开发者_开发问答mplementation details. I have implemented my version of the auto_ptr and it looks like this:
#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
My class is doing pretty much the job then I have read this question and it is clear why auto_ptr_ref is there for. However I would like to have an actual example when the auto_ptr behaves differently without add auto_ptr_ref.
My implementation works correctly with this functions:
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;
}
With this test program:
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;
I am sure I am missing something,can you give me an example where the auto_ptr_ref struct and the conversion operators are mandatory to get the correct behaviour?
Thanks
Your very first line
test::auto_ptr<double> copyConstructed(source<double>());
is already non-compilable by any standard-compliant compiler. MSVC will allow it when the C++ language extensions are enabled. Disable the extensions and you will immediately realize the need for auto_ptr_ref
.
The mechanics behind auto_ptr_ref
was too complicated for MSVC 6.0, so in order to support some resemblance of full std::auto_ptr
functionality that compiler had to rely on this compiler extension, i.e. allowing non-const references to be bound to temporary objects. The problem was fixed in later versions of the compiler, but this compiler extension remains enabled by default to this day.
You seem to be using compiler extension. I don't see a copy constructor with const reference argument. As you can't pass a temporary to a non const reference,
test::auto_ptr<double> copyConstructed(source<double>());
should fail to compile (the result of source<double>()
being a temporary).
(Note that in C++0X, rvalue reference are a better mean to achieve the effect).
精彩评论