我们最常见的错误就是用到智能指针auto_ptr的地方了,一碰到智能指针拷贝,肯定编译不通过,然后就是报个错误,
后来看到这么一篇文章: The auto_ptr Class Template
这里主要关注如下一段:
果然是这个指针在复制时候出的问题。文章的本意就有STL在设计的时候就有这个bug,后来网上一搜,果然有好多patch的信息。Details of the auto_ptr Implementation
It took the standard committee some last minute refinements to make the auto_ptr work correctly under all conditions. We mentioned earlier that correct copy construction of const and non-const auto_ptr objects is not trivial and involves some tricky design issues. So far, we have spared you the details. Let us now take a look at the implementation of the autoptr 's copy semantics.
We'll start our discussion with a canonically implemented copy constructor:
tempate As expected, this implementation passes the ownership of the heap object to the newly constructed auto_ptr object. Surprisingly, this copy constructor has a subtle problem with const -correctness, which we can see by considering the following function template:
auto_ptr:: auto_ptr (const auto_ptr & rhs) // just a try !!!
{
pointer = rhs.pointer;
rhs.pointer = 0;
}tempate The function foo() receives a const reference to an auto_ptr as parameter and does nothing except constructing a new auto_ptr as a copy of the received function argument. As the copy constructor passes the ownership of the heap object to the newly constructed auto_ptr , the original auto_ptr which foo() received as a const reference, loses the ownership. This means that after invocation of foo() , we cannot access the heap object any longer because the auto_ptr we provided to foo() does not own it any more. In other words, the auto_ptr object, that we passed to the function foo() via a const reference, is modified, and this is not exactly what we expect when we pass a const reference as a parameter to a function.
void foo(const auto_ptr& atp)
{
auto_ptrnewAtp(atp);
}
...
auto_ptrapi(new int(2));
foo(api);
...Obviously, this implementation of the copy constructor is incorrect. How can we fix it? Let us make the copy constructor?s parameter a non-const reference. As a consequence, foo() also has to make its parameter a non-const reference when it wants to invoke the copy constructor. The signature of the function foo() would then clearly express that the function argument will be modified by the function and no silent changes of constant auto_ptr objects can happen anymore.
What are the consequences of providing a copy constructor that takes a non- const reference? The problem is that such a copy constructor is not sufficient for the implementation of the auto_ptr ?s copy semantics, in particular is does not allow copies of rvalues. In order to copy an rvalue a copy constructor, that takes a const reference, is required. Consider the following situation:
auto_ptr Line 7 does not compile because the return code of the function f() is a rvalue ,and rvalues cannot be bound to non-const references, but our copy constructor requires a non-const reference as an argument. It is certainly not trivial to figure out a solution for this problem. On the one hand, we try to avoid a copy constructor that takes a const reference, while on the other hand such a copy constructor is needed to copy-construct rvalues.f();
...
auto_ptrapi( f() ); // line 7
...The solution, that works for the auto_ptr , is to allow the 'copy construction from rvalues' by means other than a copy constructor. Instead of providing a copy constructor that takes a const reference, a helper class is introduced along with conversions to and from this new type. The auxiliary class is a nested class called auto_ptr_ref, which holds a reference to an auto_ptr as data member. The conversion from an auto_ptr to an auto_ptr_ref is defined by means of a cast operator auto_ptr::operator auto_ptr_ref() and back from an auto_ptr_ref to an auto_ptr by means of a converting constructor auto_ptr::auto_ptr(auto_ptr_ref) .
The code sample below shows the declaration of the auto_ptr class template as specified in the standard; the portions that have to do with the helper class are high-lighted.
template class auto_ptr {
templatestruct auto_ptr_ref {};
public:
typedef X element_type;
// construct/copy/destroy:
explicit auto_ptr(X* p =0) throw();
auto_ptr(auto_ptr&) throw();
templateauto_ptr(auto_ptr &) throw();
auto_ptr& operator=(auto_ptr&) throw();
templateauto_ptr& operator=(auto_ptr &) throw();
~auto_ptr() throw();
// members:
X& operator*() const throw();
X* operator>() const throw();
X* get() const throw();
X* release() throw();
void reset(X* p =0) throw();
// conversions:
auto_ptr(auto_ptr_ref) throw();
templateoperator auto_ptr_ref () throw();
templateoperator auto_ptr () throw();
};
Now, when an auto_ptr object returned from a function shall be used to copy-construct another auto_ptr object, as in our example above, a conversions takes place instead of a copy construction, because the normal copy constructor is not available. Let's reconsider the example:auto_ptr In line 7 the compiler is asked to construct an auto_ptr object from an auto_ptr rvalue, namely the object returned from f() . The only viable constructor is auto_ptr::auto_ptr(auto_ptr_ref) . Hence, the compiler looks for a conversion sequence that turns the auto_ptr rvalue into an auto_ptr_ref object. This conversion is achieved via the cast operator, which creates an auto_ptr_ref that holds a reference to the auto_ptr rvalue. This temporary auto_ptr_ref object is eventually used to construct the auto_ptr object api . (Note, that the latter construction, as usual for auto_ptr s, transfers the ownership of the heap object from the auto_ptr reference contained in auto_ptr_ref to the newly constructed auto_ptr object.)f();
...
auto_ptrapi( f() ); // line 7
...
自己怎么改都是错。。。
不管了,死马当作活马医,到sgi下载一个最新的memory文件。。。
竟然搞定!
Hoory~~~
没有评论:
发表评论