strange behavior of vector class
Code :
------------------------------------------------------
Code:
class passByValueSucks
{
public :
passByValueSucks(){}
passByValueSucks(const passByValueSucks& p) { cout << "copy constructor called o no" << endl ; }
passByValueSucks& operator=(const passByValueSucks& p)
{
if (this == &p) return *this;
cout << "operator = " << endl ;
return *this;
}
};
int main(int argc, char* argv[])
{
passByValueSucks d;
cout << "test vector " << endl ;
vector<passByValueSucks> v ;
v.push_back(d);
v.push_back(d);
v.push_back(d);
v.push_back(d);
system("pause");
return 0;
}
Results :
--------------------------------------------
Code:
test vector
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
copy constructor called o no
Questions :
1) why does the vector call 10 times the copy constructor ?
i would expect at max 4 times.
2) it is an overkill that vector calls copy constructor, ( cost to call normal constructor + copy constructor). Any way to make vector not pass by value but by reference and call delete when all when it gets deleted ? or do i have to create my own vector class.
Re: strange behavior of vector class
Quote:
1) why does the vector call 10 times the copy constructor ?
i would expect at max 4 times.
Vector guarantees that its contents are held in contiguous storage like an array. Every time you call push_back, it must...
allocate new storage
copy all current elements to the new storage
copy the new element
If you know ahead of time how large the vector needs to be, you can reserve storage ahead of time by either passing the size to the constructor or using the reserve() method. Since the vector won't need to reallocate on every operation, you avoid all the extra copies.
Quote:
2) it is an overkill that vector calls copy constructor, ( cost to call normal constructor + copy constructor). Any way to make vector not pass by value but by reference and call delete when all when it gets deleted ? or do i have to create my own vector class.
Vector has to do the copying in order to work the way it's meant to. If need to do a lot of adding or removing items, a different contains like a linked list may be more appropriate.
You can use a vector to hold pointers, but you will be responsible for deleting them. To have it done automatically you'll either need to store shared_ptrs or look at boost::ptr_vector.
Re: strange behavior of vector class
Quote:
Originally Posted by Speedo
Vector guarantees that its contents are held in contiguous storage like an array. Every time you call push_back, it must...
allocate new storage
copy all current elements to the new storage
copy the new element
To be more accurate, this reallocation need not occur every time you call push_back (and in fact if it does, the implementation does not conform to the C++ standard), since the capacity is guaranteed to increase by some factor, and it may even be the case that the default initial capacity is sufficient to hold those few elements without reallocation. Consequently, how many times the copy constructor is called is implementation dependent.
Re: strange behavior of vector class
Quote:
Originally Posted by
anonymous12345
1) why does the vector call 10 times the copy constructor ? i would expect at max 4 times.
Never predict how many times a copy constructor or assignment operator is called.
It could have been called 4 times, 5 times, or 20 times. The reason is that the compiler can optimize away copy construction and have it do less than you expected, or it could be a special build option where the compiler maximizes the number of copies (i.e. does not optimize anything).
So the answer to questions such as "how many times should the copy constructor be called?" is -- it depends. It depends on the compiler, compiler options, etc.
Quote:
or do i have to create my own vector class.
And you'll wind up with the same issue. If you are trying to create a container that stores copies of objects, how are you going to get around the fact that C++ objects must be copy constructed to do the copies?
Regards,
Paul McKenzie
Re: strange behavior of vector class
Quote:
Originally Posted by
Paul McKenzie
Never predict how many times a copy constructor or assignment operator is called.
It could have been called 4 times, 5 times, or 20 times.
Ya, but it is still a mystery why this implementation calls the copy constructor 10 times. It should be called 4 times. The vector reserves the space in advance anticipating future push_backs when we do a push_back and this should not call the copy constructor.
Re: strange behavior of vector class
Quote:
Originally Posted by rohshall
Ya, but it is still a mystery why this implementation calls the copy constructor 10 times. It should be called 4 times. The vector reserves the space in advance anticipating future push_backs when we do a push_back and this should not call the copy constructor.
I am amazed that you agreed with the statement that one should "never predict how many times a copy constructor or assignment operator is called", and immediately thereafter boldly insisted that the copy constructor should have been called 4 times.
Let us suppose that the capacity of the vector starts out as 1. Suppose also that the amount of space is increased by a factor of 1.5, rounded up, whenever reallocation is done by push_back. This of course would mean that push_back runs in amortized constant time, as required by the C++ standard.
Now, on the first call to push_back, the copy constructor is called once. On the second call to push_back, there is reallocation, thus the copy constructor is called twice (the capacity is now 2). On the third call to push_back, again there is reallocation, then the copy constructor is called thrice (the capacity is now 3). On the fourth call to push_back, there is reallocation, thus the copy constructor is called four times (the capacity is now 5). 1 + 2 + 3 + 4 = 10. What's the problem?
Re: strange behavior of vector class
Quote:
Originally Posted by
rohshall
Ya, but it is still a mystery why this implementation calls the copy constructor 10 times. It should be called 4 times.
I guess you didn't read my post. One more time:
You cannot predict the number of times a copy constructor is called..
You say you agreed with that statement, then you went ahead and predicted it should be called 4 times. Doesn't that sound contradictory to you?
Quote:
The vector reserves the space in advance anticipating future push_backs when we do a push_back and this should not call the copy constructor.
Instead of guessing how the implementation should work, look at the code for vector<T>::push_back for your implementation in the <vector> header file. All of the answers to your questions are right there.
Regards,
Paul McKenzie
Re: strange behavior of vector class
Quote:
Originally Posted by
rohshall
The vector reserves the space in advance anticipating future push_backs when we do a push_back and this should not call the copy constructor.
It reserves some space in advance. How much is implementation-defined.
If you really want to see only 4 copies, your best best would be to call v.reserve(4) prior to the 4 push_backs. That gives you some control over how much space is actually reserved. (I say "some" because the vector may actually reserve more; what you specify is merely a lower bound.)
Re: strange behavior of vector class
Quote:
Originally Posted by
laserlight
I am amazed that you agreed with the statement that one should "never predict how many times a copy constructor or assignment operator is called", and immediately thereafter boldly insisted that the copy constructor should have been called 4 times.
Let us suppose that the capacity of the vector starts out as 1. Suppose also that the amount of space is increased by a factor of 1.5, rounded up, whenever reallocation is done by push_back. This of course would mean that push_back runs in amortized constant time, as required by the C++ standard.
Now, on the first call to push_back, the copy constructor is called once. On the second call to push_back, there is reallocation, thus the copy constructor is called twice (the capacity is now 2). On the third call to push_back, again there is reallocation, then the copy constructor is called thrice (the capacity is now 3). On the fourth call to push_back, there is reallocation, thus the copy constructor is called four times (the capacity is now 5). 1 + 2 + 3 + 4 = 10. What's the problem?
Great. Perfectly understood now. Thanks.
Re: strange behavior of vector class
Yes, I agree with the explanation.
And in addition, I would suggest you do a rather smalltrivial experiment - simply try to see how many elements you traverse if you iterate through your entire vector. Of course it will be 4 (no matter how many times the copy constructor is called) - at least that iswhat I expect. In that case, the functionality of your code is not disturbed.
Just my 2 cents from a practical usability angle.
__________________
Far Infrared Sauna