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)
According to C++ copy constructor, we pass an object by reference to the copy function Object() { [native code] }, and we usually pass it as a const reference. One justification for passing a const reference is that it can use const wherever possible in C++ to avoid unintentionally changing objects.
When we create our own copy constructor, we pass an object by reference and we generally pass it as a const reference. One reason for passing const reference is, we should use const in C++ wherever possible so that objects are not accidentally modified.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With