Francesco said:
Francesco S. Carta wrote:
So, do we really need to set the pointers to null before destroying
the vector?
As it seems, formally, yes [*], we need to nullify them,
because the actions performed by the vector during
reallocation or during destruction might lead to that lvalue
to rvalue conversion, thus calling UB into play.
Formally, you need to nullify the pointer in the vector before
deleting it, since nullifying it (assigning NULL to it) involves
accessing into the vector, which could theoretically lead to an
lvalue to rvalue conversion.
So to be formally fine I need something like this...
vector<sometype*> vec;
vec.push_back(new sometype);
sometype* ptr = vec[0];
vec[0] = 0;
delete ptr;
...or variations thereof. Thank you for the correction.
Well, that is a somewhat contested issue. More importantly, though, it is
based upon an interpretation of language that is subject to heavy changes
in C++0x. My preliminary understanding of is that a contorted work-around
like the above is not necessary under the C++0x rules.
For your very words, it has to be proved formally necessary even in
C++03, for that matter.
Ok, for C++0x some of the issues for interpreting the standard are:
a) How does 4.1/1 imply that lvalue-rvalue conversion of invalid pointers is
UB? The wording is:
If the object to which the lvalue refers is not an object of type T and is
not an object of a type derived from T, or if the object is uninitialized,
a program that necessitates this conversion has undefined behavior.
Code example:
int* p = new int();
delete p;
int* q = p; // lvalue-rvalue conversion
So, in this example, is the object to which p refers not of type int*? or is
the the object analogous to an uninitialized object?
Assuming the first alternative, we find that
std::vector< int*> v;
v.push_back( new int () );
delete v.back();
creates a vector whose elements are not objects of type int*. In fact, it
would be hard to say what the type of the stored object is. In particular,
is the type of the object in the vector CopyConstructible?
b) How to precisely interpret CopyConstructibility (table 30). E.g.,
int* p = new int();
delete p;
// is int* CopyConstructible at this point?
If one would arge a strong NO here, we arrive at _very_ unwelcome
consequences:
std::vector<int*> v;
v.push_back( new int () );
int* p = new int ();
delete p;
std::vector<int*> w ( v );
The last line would be UB if int* was not CopyConstructible.
Note: I don't wand to suggest how to resolve these issues of interpretation.