Let's add a copy constructor (and use a smaller test case, to cut the verbosity) and see what happens...
#include <iostream>
#include <string>
#include <vector>
class Test
{
public:
std::string name;
Test(){};
Test(std::string name) : name(name) {
std::cout << "New " << name << '\n';
}
Test(const Test& other) : name("Copy of " + other.name) {
std::cout << "Copied " << other.name << '\n';
}
~Test() {std::cout << "Destroy " << name << '\n';}
};
std::vector<Test> test {Test("Original") };
int main()
{
std::cout << "Loop:\n";
for (auto i : test)
std::cout << "This is " << i.name << '\n';
std::cout << "Clear\n";
test.clear();
}
This produces
New Original
Copied Original
Destroy Original
Loop:
Copied Copy of Original
This is Copy of Copy of Original
Destroy Copy of Copy of Original
Clear
Destroy Copy of Original
Explanation:
New Original -- The object in the initialzer list
Copied Original -- Here it gets copied into the vector
Destroy Original -- The original is destroyed along with the initializer list
Loop:
Copied Copy of Original -- Copied into the loop variable
This is Copy of Copy of Original -- Printing in the loop
Destroy Copy of Copy of Original -- The temporary loop object is destroyed
Clear
Destroy Copy of Original -- Clearing the vector
If you loop over references, i
will refer to the object inside the vector instead of a copy of it - just changing one line to
for (auto& i : test)
changes the output to
New Original
Copied Original
Destroy Original
Loop:
This is Copy of Original
Clear
Destroy Copy of Original
And you can get rid of further copying by creating the object inside the vector directly:
int main()
{
std::vector<Test> test;
test.emplace_back("Original");
std::cout << "Loop:\n";
for (auto& i : test)
std::cout << "This is " << i.name << '\n';
std::cout << "Clear\n";
test.clear();
}
Output:
Original
Loop:
This is Original
Clear
Destroy Original