C ++: damage to vector memory when modifying an object member from outside the copy constructor, but not when changing from the inside

#include <iostream> #include <vector> #include <cassert> class a_class { public: int num_IN; a_class():num_IN(0){} a_class(a_class const & origin){/*Initialise();*/} //if not called here, error occurs void Initialise(){num_IN =5;} }; int main () { std::vector <a_class> the_vector; for(int q=0; q < 30; q++) { the_vector.push_back(a_class()); the_vector[q].Initialise(); assert(5 == the_vector[q].num_IN); //no problem here } for(int q=0; q < 30; q++) assert(the_vector[q].num_IN == 5); //assertion fails } 

I do not understand the difference between calling this from outside and inside CC. I also don't know why this should cause a problem anyway.

+4
source share
5 answers

std::vector can redistribute the used buffer if it changes its size, in which case it should copy the old elements to the new buffer. If you do not have a suitable copy constructor that copies num_IN , the old value will be lost.

Correct this by providing the correct copy constructor:

 a_class(a_class const & origin) : num_IN(origin.num_IN) {} 

In the submitted code, the copy constructor is not even needed - if you do not provide it, the compiler will generate the appropriate one here.

+4
source

In the std::vector class, you may need to redistribute the main dynamic array when you repeatedly call push_back() to add new elements. A common strategy is to std::vector increase the size of the base buffer by a factor, possibly a factor of 2 .

When this redistribution really happens, the copy constructor (or the move constructor, if you define it and use c++0x ) is called to copy the vector elements from the old buffer to the new one.

Your copy constructor does not actually copy correctly, you must assign the num_IN parameter:

 a_class(a_class const& src): num_IN(src.num_IN) {} 

Typically, with STL containers, stored data types must obey a three- rule rule in that the constructor, copy constructor, assignment operator, and destructor all work together.

With move semantics in c++0x I assume that this should be extended to the β€œrule of five” in that you should also consider correctly defined move constructors and move assignment operators.

+3
source

The problem is with push_back , your vector reallocates memory in the first for loop whenever the size vector increases beyond its capacity . During this redistribution, vector copies the objects already present in it by calling the copy constructor. Since your copy constructor is incorrect (you are not doing anything there), the initialized value is not carried over during the redistribution.

+2
source

Your copy constructor does nothing. This should be indicated num_IN = origin.num_IN;

+1
source

Ahhh,

I see what is happening.

In the first loop, you return the object back to the vector, each time you click back, the vector changes, and the copy constructor is now called for all elements of the vector. Since you have overwritten the copy constructor to do nothing, num_IN remains uninitialized.

for it to work. I could reuse the copy constructor to make a member wise copy.

As an alternative.

i will resize the vector to the required size. Thus, the vector does not change every time you add an additional element

 std::vector <a_class> the_vector; the_vector.resize(30); for(int q=0; q < 30; q++) { the_vector[q].Initialise(); assert(5 == the_vector[q].num_IN); //no problem here } for(int q=0; q < 30; q++) assert(the_vector[q].num_IN == 5); //assertion fails 
+1
source

All Articles