In an answer to Is it safe to store objects of a class which has an std::auto_ptr as its member variable in std::vector? I stated that a class that contained an auto_ptr could
Trying to put the list of places together that makes the example undefined behavior.
#include
#include
using namespace std;
struct Z {};
struct A {
A( Z z )
: p( new Z(z) ) {}
A( const A & a )
: p( a.p.get() ? new Z( *a.p.get()) : 0 ) {}
// no assigment op or dtor defined by intent
auto_ptr p;
};
int main() {
vector av;
...
}
I will examine the lines up to the one where you instantiate the vector with your type A. The Standard has to say
In 23.1/3:
The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.
In 23.1/4 (emphasis mine):
In Table 64, T is the type used to instantiate the container, t is a value of T, and u is a value of (possibly const) T.
+-----------+---------------+---------------------+ |expression |return type |postcondition | +-----------+---------------+---------------------+ |t = u |T& |t is equivalent to u | +-----------+---------------+---------------------+Table 64
In 12.8/10:
If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. The implicitly-declared copy assignment operator for a class X will have the form
X& X::operator=(const X&)if
- each direct base class B of X has a copy assignment operator whose parameter is of type const B&, const volatile B& or B, and
- for all the nonstatic data members of X that are of a class type M (or array thereof), each such class type has a copy assignment operator whose parameter is of type const M&, const volatile M& or M.
Otherwise, the implicitly declared copy assignment operator will have the form
X& X::operator=(X&)
(Note the last and second last sentence)
In 17.4.3.6/1 and /2:
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ Standard Library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
- for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause (20.1.5, 23.1, 24.1, 26.1). Operations on such types can report a failure by throwing an exception unless otherwise specified.
Now, if you look at the specification of auto_ptr you will note it has a copy-assignment operator that takes a non-const auto_ptr. Thus, the implicitly declared copy assignment operator of your class will also take a non-const type as its parameter. If you read the above places carefully, you will see how it says that instantiating a vector with your type as written is undefined behavior.