Reputation: 5255
I have the following code:
struct Position{
int id;
Position(int _id){
id = _id;
qDebug()<<"Position"<<id;
}
~Position(){
qDebug()<<"~Position "<<id;
}
};
qDebug()<<"Init";
std::vector<Position> vec1;
vec1.emplace_back(1);
std::vector<Position> vec2;
vec2.emplace_back(2);
std::vector<Position> vec3;
vec3.emplace_back(3);
qDebug()<<"Move";
vec2 = vec1;
qDebug()<<"---------------------------------";
What happens when I do = ? Shouldn't previous object vec2 be destructed? I read this http://www.cplusplus.com/reference/vector/vector/operator=/, but still not undestand what should happend with old vec2 object.
Output:
Init
Position 1
Position 2
Position 3
Move
---------------------------------
~Position 3
~Position 1
~Position 1
Why Position 2 not destructed at all?
Upvotes: 0
Views: 302
Reputation: 476950
The container requirements (C++11 23.2.1) for assignment say:
All existing elements of a are either move assigned to or destroyed
(Actually that is only for assignment of an rvalue. For assignment of an lvalue, there's no specification at all other than that the two containers shall be equal afterwards.)
So it's up to the implementation whether the original elements are destroyed, or overwritten element-wise.
If you want to destroy the original container and replace it with a copy of another container unconditionally, you can use swap
like so:
// instead of "x = y"
std::vector<Position>(y).swap(x);
This constructs a new vector as a copy of y
and swaps that with x
, and swapping doesn't touch the actual container elements - again from the container requirements:
a.swap(b)
shall exchange the values of a and b without invoking any move, copy, or swap operations on the individual container elements
Upvotes: 3
Reputation: 264351
Adding more print statements for compiler generated functions.
#include <iostream>
#include <vector>
// Don't have this on my machine so added
// to make it similar to the original
std::ostream& qDebug()
{
return std::cout;
}
struct Position{
int id;
Position(int _id){
id = _id;
qDebug()<<"Position"<<id <<"\n";
}
~Position(){
qDebug()<<"~Position "<<id <<"\n";
}
// Added this. Because if you don't define one
// the compiler will.
// Made it do the default action and print
Position(Position const& rhs)
: id(rhs.id)
{
qDebug() <<"Copy: " << id <<"\n";
}
// Added this. Because if you don't define one
// the compiler will.
// Made it do the default action and print
Position& operator=(Position const& rhs)
{
qDebug() << "Assign: Old(" << id << ") New(" << rhs.id << ")\n";
id = rhs.id;
return *this;
}
};
int main()
{
qDebug()<<"Init\n";
std::vector<Position> vec1;
vec1.emplace_back(1);
std::vector<Position> vec2;
vec2.emplace_back(2);
std::vector<Position> vec3;
vec3.emplace_back(3);
qDebug()<<"Move\n";
vec2 = vec1;
qDebug()<<"---------------------------------\n";
}
Now we run it:
> ./a.out
Init
Position1
Position2
Position3
Move
Assign: Old(2) New(1)
---------------------------------
~Position 3
~Position 1
~Position 1
So we can see that Position(2) got overwritten by an assignment that placed (1) into the value. The most important thing to note is that the number of constructors and destructors match.
Upvotes: 2
Reputation: 310930
Your class position has no explicitly defined copy-assignment operator. When this statement
vec2 = vec1;
is executed the copy assignment operator for elements the number of which is common for the both vectors is called. So vec2[0] is substituted for vec1[0] (that is vec1[0] is assigned to vec2[0]). It means that old element vec2[0] gets id equal to 1. Nothing is deleted.
When destructors are called vec2[0] has id equal to 1 and vec1[0] has id equal to 1 because this element was assigned to vec2[0]. The output shows this.
Upvotes: 0
Reputation: 385108
When you write vec2 = vec1
, vec2
takes on copies of all the elements of vec1
. How could it do that if it ceased to exist?
Now, as for vec2
's elements, they don't need to be destroyed when they can be copied/moved† over instead. The language allows either to happen.
If you write your own copy/move assignment operators and put debug output in those, you'll see what's really going on.
† Depending on C++ version.
Upvotes: 4