#include <utility>
#include <vector>
#include "iostream"
class Person {
public:
std::string name{"no-name"};
Person() {
std::cout << std::string("Person()") << std::endl;
}
explicit Person(std::string name) : name(std::move(name)) {
std::cout << std::string("Person(") + this->name + ")" << std::endl;
}
// operator =
Person &operator=(const Person &other) {
std::cout << std::string("operator= ") + other.name + "->" + this->name + "" << std::endl;
return *this;
}
Person(const Person &other) noexcept {
std::cout << std::string("copy ") + other.name + "->" + this->name + "" << std::endl;
this->name = other.name;
}
// move
Person(Person &&other) noexcept {
std::cout << std::string("move ") + other.name + "->" + this->name + "" << std::endl;
this->name = std::move(other.name);
}
~Person() {
std::cout << std::string("~Person(") + name + ")" << std::endl;
}
};
int main() {
std::cout << "construct person_list" << std::endl;
std::vector<Person> person_list (4);
std::cout << "construct person_list_copy" << std::endl;
std::vector<Person> person_list_copy (person_list.begin(), person_list.end());
}
output:
construct person_list
Person()
Person()
Person()
Person()
construct person_list_copy
copy no-name->no-name
copy no-name->no-name
copy no-name->no-name
copy no-name->no-name
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
Where does the enough space of vector "person_list_copy" come from before the copy operation took place?
I think the vector is much like a C-style fixed-size array, we firstly need to have enough space where I think the default constructor should be called, and then we assign some objects into those pre-constructed "cells", at which I think copy constructor should be called.
The code above directly creates object with copy constructor, but how is that possible to put an object into an array before the space of the array is constructed?
I never saw something like this before in terms of C programming. And I can't figure out an available way to achieve something like what std::vector does with all terminologies I've got so far, like 'new', uint8_t fixed_array[LEN], malloc.
I'm a C++ beginner, and there must be some misunderstanding of vector range initialization in my head, or may be there are some magics I don't know yet about C++ and STL.
Expected output
construct person_list
Person()
Person()
Person()
Person()
construct person_list_copy
Person()
Person()
Person()
Person()
copy no-name->no-name
copy no-name->no-name
copy no-name->no-name
copy no-name->no-name
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
~Person(no-name)
Well, that's what C++ can do and does if possible. Allocates empty memory first, calls constructors later. std classes are intentionally written to do this to save CPU time.
In C++ you have full control over the raw memory and you can choose to do with it as you please. Including stuff like leaving it uninitialized or forcibly calling initialization on an arbitrary chunk of memory.
See https://www.geeksforgeeks.org/placement-new-operator-cpp/ for example of how it can be done under the hood.