main.cpp
#include <iostream>
#include <vector>
#include "Person.h"
using namespace std;
int main()
{
vector<Person> test{};
test.push_back (Person{ "Chinese", 16 });
test.push_back(Person{});
return 0;
}
Person.h
#pragma once
#include <iostream>
class Person
{
public:
std::string* ethnicity;
int age;
Person(std::string ethnicity = "Caucasian", int age = 15);
~Person();
Person(const Person& source);
Person (Person&& source) noexcept;
};
Person.cpp
#include "Person.h"
Person::Person(std::string ethnicity, int age)
: age(age)
{
this->ethnicity = new std::string;
*this->ethnicity = ethnicity;
}
Person::Person(const Person& source)
: Person(*source.ethnicity, source.age)
{
std::cout << "Copy constructor deep called!" << std::endl;
}
Person::Person(Person&& source) noexcept
: ethnicity(source.ethnicity), age(source.age)
{
std::cout << "Move constructor called!" << std::endl;
source.ethnicity = nullptr;
}
Person::~Person()
{
if (this->ethnicity != nullptr)
std::cout << "Destructor called!" << std::endl;
else
std::cout << "Destructor called for nullptr!" << std::endl;
delete ethnicity;
}
Output
From my understanding, only 2 move constructors should be called. But why are 3 move constructors called? The first push_back()
should create a temporary object through the constructor, and then the move constructor will be called, then the destructor would be called for the temporary object. The process would be the same for the 2nd push_back()
, so in total there would only be 2 move constructors getting called. But why are there 3?
CodePudding user response:
But why are there 3?
When std::vector
needs more space, it allocates a new array and copies/moves all the existing elements from the old array to the new array.
Solution 1
To minimize this, use the std::vector::reserve()
member function before pushing elements onto the vector. This pre-allocates the needed space.
vector<Person> test;
test.reserve(2);
test.push_back(Person{"Chinese", 16});
test.push_back(Person{});
Solution 2
Or you can create the vector to be of a particular size, like:
vector<Person> test(2);
test.at(0) = Person{"Chinese", 16};
test.at(1) = Person{};
Note that in solution 2, we first create a vector
of size 2. Now since the std::vector
is already of size 2, we do not use push_back
because this will mean we add more elements to the vector
and the vector
size will increase and become 4(if we use push_back
2 times) which is not what we want. What we want now is to set the 0th
and 1st
index element. Just make sure you handle(or add the assignment operator= if not already) assignment correctly in solution 2.