Pregunta

The following code does not compile on Visual C++ 2008 nor 2010:

#include <memory>

struct A {};

      std::auto_ptr<A> foo()  { return std::auto_ptr<A>(new A); }
const std::auto_ptr<A> bar()  { return std::auto_ptr<A>(new A); }

int main()
{
   const std::auto_ptr<A> & a = foo(); // most important const

   const std::auto_ptr<A> & b = bar(); // error C2558:
                                       // class 'std::auto_ptr<_Ty>' :
                                       // no copy constructor available or copy
                                       // constructor is declared 'explicit'

                                bar(); // No error?
}

I expected the "most important const" to apply to the variable "b", and yet, it does not compile, and for some reason, the compiler asks for a copy constructor (which surprises me as there should be no copy involved here). The standalone call to bar() works fine, which means, I guess, it is really the initialization of b that is the problem.

Is this a compiler bug, or a genuine compilation error described in the standard?

(perhaps it was forbidden in C++98 and authorized in C++11?)

Note: It does compile on Visual C++ 2012, gcc 4.6, and on Solaris CC (of all compilers...), but not gcc 3.4, nor XL C)

¿Fue útil?

Solución

In C++03 and C++98, when binding a const reference to an rvalue (such as a function returning by value), the implementation may bind the reference directly to the rvalue or it may make a copy of the rvalue and bind the reference to that copy. As auto_ptr's copy constructor takes a non-const reference, this second choice will only work if the rvalue returned is not const qualified but the compiler is still allowed to attempt this, even if it won't work.

In C++11, these extra copies are not allowed and the implementation must bind directly to the rvalue if a conversion isn't required.

See also here.

Otros consejos

Pre C++11, at least, the standard required an object to be copyable in this context. In the end, the semantics of:

T const& t = f();

, where f returns a T by value, is:

T tmp = f();
T const& t = tmp;

Which requires a copy constructor.

In the case of std::auto_ptr, the problem that you're seeing is that the copy constructor is defined to take a non-const reference, which means that you cannot copy a temporary. Some compilers (e.g. Microsoft) don't enforce this, which means that your code may work with them, but it is fundamentally illegal.

The real question is why you are using references here. You need a local variable one way or the other; the reference only introduces an additional layer of indirection.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top