You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:27:08