WAS: why it seems that std::list::erase() doesnt free objects in a list, if the latter holds pointer

J

jimjim

Hello again,
Consider the following code:

#include <iostream>
#include <list>

class X {
private:
int val;
public:
X(int v){ cout << "X constructor\n"; val = v;}
~X() { cout << "X destructor\n"; }
X( X const & ) { cout << "X copy constructor\n"; }
int return_val() {return val;}
};

int main(){
X x(6);
list<X>lists;
lists.push_back(x);
list<X>::iterator i = lists.begin();
cout << (*i).return_val()<<endl;
lists.erase(lists.begin());
}
The output is as expected:
X constructor
X copy constructor
0
X destructor
X destructor

Why is 0 returned by the return_val() and not 6? I assume when I push the x
object into the list, I copy both the object and the state.
 
J

Jeff Flinn

jimjim said:
Hello again,
Consider the following code:

#include <iostream>
#include <list>

class X {
private:
int val;
public:
X(int v){ cout << "X constructor\n"; val = v;}
~X() { cout << "X destructor\n"; }
X( X const & ) { cout << "X copy constructor\n"; }
int return_val() {return val;}
};

int main(){
X x(6);
list<X>lists;
lists.push_back(x);
list<X>::iterator i = lists.begin();
cout << (*i).return_val()<<endl;
lists.erase(lists.begin());
}
The output is as expected:
X constructor
X copy constructor
0
X destructor
X destructor

Why is 0 returned by the return_val() and not 6? I assume when I push the x
object into the list, I copy both the object and the state.

Given X's copy constructor, why would you expect it to be 6?

Jeff F
 
J

jimjim

thx for the fast reply.

As I mentioned, I assume that when I push an object into a list I copy the
whole object (ie the values of its member variables). I guess the copy
constructor prevents from copying the values that an object had when it is
copied right?
 
J

jimjim

As I mentioned, I assume that when I push an object into a list I copy the
whole object (ie the values of its member variables). I guess the copy
constructor prevents from copying the values that an object had when it is
copied right?
As if I comment out the copy constructor from the class definition, the
result is:
X constructor
6
X destructor
X destructor
 
L

Leor Zolman

As if I comment out the copy constructor from the class definition, the
result is:
X constructor
6
X destructor
X destructor

When you wrote your own copy constructor, that's the one that was used.
Your version didn't copy anything, so you got "default initialization"
behavior: the new object's data member was set to zero (to be honest, I
never realized that copy ctors would do that, and I haven't yet found where
in the Standard that behavior is specified. But that's what it seems to be
doing.)

When you removed your own definition of the copy ctor, /then/ the compiler
generated one for you that did a member-wise copy of the class's data
members, and you got the desired behavior.
-leor
 
J

Jeff Flinn

Leor Zolman said:
When you wrote your own copy constructor, that's the one that was used.
Your version didn't copy anything, so you got "default initialization"
behavior: the new object's data member was set to zero (to be honest, I
never realized that copy ctors would do that, and I haven't yet found where
in the Standard that behavior is specified. But that's what it seems to be
doing.)

I was under the impression that the data member would not be initialized at
all, and that the zero was just luck. Or if the op's code was compiled in
debug, on some compilers the memory is set to zero when allocated.

Jeff F
 
J

John Harrison

jimjim said:
I see thx :)

so how could I copy the values of the variables to the copy object?

X( X const & rhs) : val(rhs.val) { cout << "X copy constructor\n"; }

and your other constructor should be

X( int v) : val(v) { cout << "X constructor\n"; }

Its a good habit to get into using val(rhs.val) and val(v) instead of val =
rhs.val and val = v. The first is called initialisation and the second is
called assignment. In general initialisation is more efficient than
assignment.

john
 
J

Jeff Flinn

jimjim said:
I see thx :)

so how could I copy the values of the variables to the copy object?

Lookup copy constructor in any C++ book or the FAQ. You should also learn to
use initializer lists. Even though you should really do this yourself,
here's your original class reworked.

class X
{
int mVal;

public:
~X() { cout << "X destructor\n"; }

X( ):mVal( 0){ cout << "X default
constructor\n"; }
X( int aVal ):mVal( aVal){ cout << "X constructor\n"; }
X( X const& aRef ):mVal(aRef.mVal){ cout << "X copy constructor\n"; }

int return_val()const{ return mVal; }
};

Note the added default constructor, and the explicit initialization of the
data member in each constructor. In your original code the mVal() initilizer
list was automatically provided by the compiler. When you removed the
defective copy constructor, the compiler supplied an equivalent copy
constructor to the one shown above.

Jeff F
 
L

Leor Zolman

I was under the impression that the data member would not be initialized at
all, and that the zero was just luck. Or if the op's code was compiled in
debug, on some compilers the memory is set to zero when allocated.

I didn't try it with enough compilers. Although things got set to zero with
the first few I tried (no debug mode, and I even changed the type of the
variable in question to double, just to see if that made any
difference...and it didn't on those few platforms), as soon as I tried a
few more compilers just now, things went quickly to hell in a hand basket.

I'm actually glad, because I would have felt stupider if that /was/ the
required behavior of copy constructors and I hadn't known it...
-leor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top