I'm trying to fill a std::vector
with objects created in a function like so:
class Foo
{
public:
Foo() { std::cout << "Foo created!\n"; }
Foo(const Foo& other) { std::cout << "Foo copied!\n"; }
Foo(Foo&& other) { std::cout << "Foo moved\n"; }
~Foo() { std::cout << "Foo destroyed\n"; }
};
static Foo createFoo()
{
return Foo();
}
int main()
{
{
std::vector<Foo> fooVector;
fooVector.reserve(2);
fooVector.push_back(createFoo());
fooVector.push_back(createFoo());
std::cout << "reaching end of scope\n";
}
std::cin.get();
}
Output:
Foo created!
Foo moved
Foo destroyed
Foo created!
Foo moved
Foo destroyed
reaching end of scope
Foo destroyed
Foo destroyed
How can Foo
be destroyed more times than it is created? I don't understand what is happening here, I thought that Foo
would be copied, but the copy constructor is not triggered.
What is the best way to fill a std::vector
with objects created elsewhere without them being destroyed?
boolean add(Object element): This method appends the specified element to the end of this vector. Parameters: This function accepts a single parameter element as shown in the above syntax. The element specified by this parameter is appended to end of the vector.
Having vector of objects is much slower than a vector of pointers. The results are because algorithms such as sorting need to move elements inside the container. So they not only read the data but also perform a copy (when the algorithm decides to swap items or move to a correct place according to the order).
Arrays have to be deallocated explicitly if defined dynamically whereas vectors are automatically de-allocated from heap memory.
Elements can be added in the middle of a Vector by using the java. util. Vector. insertElementAt() method.
How can Foo be destroyed more times than it is created?
The output shows exactly as many creations, as it shows destructions:
change -> cumulative total
Foo created! +1 -> 1
Foo moved +1 -> 2
Foo destroyed -1 -> 1
Foo created! +1 -> 2
Foo moved +1 -> 3
Foo destroyed -1 -> 2
reaching end of scope
Foo destroyed -1 -> 1
Foo destroyed -1 -> 0 all objects that were created are now destroyed
I thought that Foo would be copied, but the copy constructor is not triggered.
Each time you pass an rvalue to the constructor. That is why the move constructor is used instead of copy constructor.
What is the best way to fill a std::vector with objects created elsewhere without them being destroyed?
Well, by not destroying the objects that you created elsewhere... But usually you should avoid doing that, since it is typically a memory leak.
If you create two objects elsewhere and two objects in a vector, then you end up with having created 4 objects. If you wanted only two objects, then for example create the objects directly into the vector and nowhere else. Like this for example:
fooVector.emplace_back();
fooVector.emplace_back();
When you do
fooVector.push_back(createFoo());
First createFoo()
creates a temporary Foo
object, this is why you see
Foo created!
Then, that object is "moved" into the vector since it is a prvalue. This is why you see
Foo moved
Now you have an object in the vector, but you also have that temporay object that was created, moving doesn't get rid of that object, it just moves its internals into the object in the vector. You still need to destroy that object once it goes out of scoped and that happens at the end of the full expression giving you the
Foo destroyed
output.
When you make std::move(obj)
, the state of the moved object is supposed to be a new state which can be destroyed. This happens usually by transferring the data held by the object to a new object (will be constructed using move ctor). and finally the object we have taken its content will be destroyed too.
Now each move operation will construct a new object and leave the old one in a state to be destroyed, hence you have the right output 4 constructions (2 by default ctor and two by move ctor) and the corresponding 4 destructions.
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