I have following code snippet:
std::vector<std::string> v1;
v1.push_back("Hello");
v1.push_back("World");
std::vector<std::string> v2;
v2.push_back("Good");
v2.push_back("Bye");
v1 = v2;
What will happen to the old values of vector v1
.
or
v1
destroys. Then How can I free them immediately?According to the references
Any elements held in the container before the call are either assigned to or destroyed.
So, in your example, the original underlying std::string
values will have the std::string::operator=
called on them and they (the underlying std::string
itself) will not be destroyed.
If the vector being assigned to is larger than the vector being assigned from, then you would have the destructor called for the elements in the vector, example:
std::vector<std::string> v1;
v1.push_back("Hello");
v1.push_back("There");
v1.push_back("World");
std::vector<std::string> v2;
v2.push_back("Good");
v2.push_back("Bye");
v1 = v2;
In this example, the std::string
values for "Hello"
and "There"
will be assigned "Good"
and "Bye"
respectively while the 3rd string of "World"
will be destroyed.
Remember though this applies only to the element contained in the vector, take the following code for example:
std::vector<int*> v1;
v1.push_back(new int(42));
v1.push_back(new int(24));
v1.push_back(new int(38));
std::vector<int*> v2;
v2.push_back(new int(32));
v2.push_back(new int(23));
v1 = v2;
In this code, a memory leak occurs since v1
is a vector containing pointers, the pointers themselves are assigned/destroyed, not the value it points to. This example is equivalent to the following:
int* x = new int(42);
int* y = new int(24);
x = y; // memory leak here
To this, if you wish to remove the elements from the vector (thus calling the destructor of each element in the container), you can use the clear
method, which clears all elements from the vector, or you can also use the erase
method, which can erase a single element or multiple.
The same rules apply with clear
and erase
; if the underlying type is a pointer type that has claimed memory, you need to be sure you delete
the elements in the vector; example:
template < typename IteratorType >
void delete_elements(IteratorType start, IteratorType end)
{
while (start != end) {
delete (*start); // or delete[]
++start;
}
}
std::vector<int*> v1;
v1.push_back(new int(42));
v1.push_back(new int(24));
v1.push_back(new int(38));
delete_elements(v1.begin(), v1.end());
And if you want to see this assignment in action, you can use a little test class like the following code:
#include <iostream>
#include <string>
#include <vector>
#define outi(v) std::cout << v << ", i = " << i << std::endl
class tester {
public:
tester() : i(42) { outi("default ctor"); }
tester(int x) : i(x) { outi("implicit ctor"); }
~tester() { outi("dtor"); }
tester(const tester& cp) : i(cp.i) { outi("copy ctor"); }
tester& operator=(const tester& cp) {
this->i = cp.i;
outi("operator=");
return *this;
}
// for std::cout << tester;
friend std::ostream& operator<<(std::ostream& o, const tester& t) {
o << t.i; return o;
}
private:
int i;
};
template < typename itr >
static void printall(itr start, itr end)
{
while (start != end) {
std::cout << (*start) << std::endl;
++start;
}
}
int main(int argc, char* argv[])
{
std::vector<tester> v1;
std::cout << "create v1 elements" << std::endl;
v1.push_back(10); // implicit ctor calls
v1.push_back(24);
v1.push_back(33);
printall(v1.begin(), v1.end());
std::vector<tester> v2;
std::cout << "create v2 elements" << std::endl;
v2.push_back(tester(100));
v2.push_back(tester(99));
printall(v2.begin(), v2.end());
std::cout << "v1 = v2" << std::endl;
//v1.clear(); // uncomment to call dtor's
v1 = v2;
printall(v1.begin(), v1.end());
return 0;
}
Where the output of this program might be something like the following:
create v1 elements
implicit ctor, i = 10
copy ctor, i = 10
dtor, i = 10
implicit ctor, i = 24
copy ctor, i = 10
dtor, i = 10
copy ctor, i = 24
dtor, i = 24
implicit ctor, i = 33
copy ctor, i = 10
copy ctor, i = 24
dtor, i = 10
dtor, i = 24
copy ctor, i = 33
dtor, i = 33
10
24
33
create v2 elements
implicit ctor, i = 100
copy ctor, i = 100
dtor, i = 100
implicit ctor, i = 99
copy ctor, i = 100
dtor, i = 100
copy ctor, i = 99
dtor, i = 99
100
99
v1 = v2
operator=, i = 100
operator=, i = 99
dtor, i = 33
100
99
dtor, i = 100
dtor, i = 99
dtor, i = 100
dtor, i = 99
I say might because your compiler could choose to order the constructors/assignment slightly different, but the results will be the same.
I hope that can help.
The old values of v1
are destroyed when v1
is assigned to, because the assignment removes the earlier content.
To clear a vector immediately without assigning a new value, you can use the clear
method or the resize
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With