The destructor is called when I don't want it
The destructor of the class I created is called to the end of the scope. I think it has something to do with the reallocation in the vector when I add another element to it. How can I go beyond this question? I want the destructor to be called only when the object reaches the end of the scope in my code.
#include <string>
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
~A() { cout << "destructor called\n"; }
};
int main ()
{
A one, two;
vector<A> vec;
cout << "push_back one" << endl;
vec.push_back(one);
cout << "push_back two" << endl;
vec.push_back(two);
//destructor gets called here
system("pause");
return 0;
} //while i want it to be called here
source to share
The printouts in your code do not show the complete image: the destructor is called on another object.
Take a look at this modified code. I have added address printouts and enter some other key places like assignment operator calls and copy constructor.
#include <string>
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A() {cout << "constructed " << (void*)this << "\n";}
A(const A& a) {cout << "copied " << (void*)(&a) << " to " << (void*)this << "\n"; }
A& operator =(const A& a) {cout << "assigned " << (void*)(&a) << " to " << (void*)this << "\n"; }
~A() { cout << "destructor called for " << (void*)this << "\n"; }
};
int main ()
{
A one, two;
vector<A> vec;
cout << "push_back one" << endl;
vec.push_back(one);
cout << "push_back two" << endl;
vec.push_back(two);
//destructor gets called here
return 0;
}
It outputs the following output ( demo ):
constructed 0xbff229b2
constructed 0xbff229b3
push_back one
copied 0xbff229b2 to 0x970c008
push_back two
copied 0xbff229b3 to 0x970c019
copied 0x970c008 to 0x970c018
destructor called for 0x970c008
destructor called for 0x970c018
destructor called for 0x970c019
destructor called for 0xbff229b3
destructor called for 0xbff229b2
You can see that the objects one
and two
( 0xbff229b2
and 0xbff229b3
) are not completely destroyed when they go out of bounds. Its copies, which are destroyed when the vector is resized.
source to share
According to C ++ standard Β§ 23.3.6:
Vectors have a certain capacity, which means
The total number of elements that a vector can hold without the need for reallocation
When you push_back
add an item, it actually increases the container size by one, which is
Causes redistribution if the new size is larger than the old capacity
Reallocation means that you de-select (i.e. destroy) the elements in the vector and then select (i.e. construct) them again.
Please note that in your case the original one
and the two
instances are A
not destroyed, rather their copies, which are stored in the vector.
The programmer needs to be more careful with references and iterators, because
The reallocation invalidates all references, pointers, and iterators that refer to elements in the sequence.
As mentioned, reserve()
will help prevent this because
Reallocation should not occur during insertions that occur after a call to reserve () until the insertion makes the vector size larger than the capacity () value.
source to share
As the comments suggest, you should be using std::vector<>::reserve(size_t)
.
What you see is the implementation. Most implementations roughly double the allocated allocation size as they grow. This is done in order to avoid many allocations and copies whenever the size increases.
The reservation simply suggests the collections that you need n items. The implementation, if it decides to execute the request, reallocates and moves / copies the existing values ββinto a new distribution that is large enough to hold the number of items requested. You can now come back without costly reallocation. Proper reservations can save you a lot of reallocations when resizing the container when you have a good idea what the final size will be.
Reserving in this case will avoid resizing and destroying the temporary image that you see.
You are probably seeing the destructor because the collection is resized. When you release a second time, it redistributes.
If the object should never be destroyed, you should consider a different type of collection or storage location, since the program as it stands depends on implementation-defined behavior (that is, the standard specification for a vector does not provide the guarantee you need).
source to share