C++ vector调用push_back时为何移动构造函数被调用3次?
问题相关代码
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; }
问题解答
多出的1次移动构造是std::vector的动态扩容机制导致的:
- 空vector初始化后默认容量为0,没有预分配内存。
- 第一次调用
push_back时,vector分配1个元素大小的内存,将临时构造的Person对象移动存入,此时size=1、capacity=1,对应第1次移动构造。 - 第二次调用
push_back时,现有容量1无法容纳2个元素,触发扩容逻辑:首先申请2个元素大小的新内存,将原内存中已存储的1个Person对象移动到新内存地址,这就是额外产生的第2次移动构造;之后再将第二次创建的临时Person对象移动存入新内存的第二个位置,对应第3次移动构造。 - 扩容完成后,原内存中的旧对象会被析构释放。
如果要规避这次额外的移动构造,可以在插入元素前提前预留足够空间,在创建vector后添加test.reserve(2);即可,此时vector提前分配好容纳2个元素的内存,不会触发扩容,最终只会输出2次移动构造,和预期一致。
内容的提问来源于stack exchange,提问作者Brad
相关产品推荐
相关产品推荐

