C++嵌套vector执行push_back时二维vector出现重复值的问题排查与解决
问题:C++中vector存储自定义类时,内层vector元素累积重复
我定义了一个存储自定义类classe的vector,这个类里包含一个vector<int>类型的成员vetint。现在遇到的问题是,每次给外层vector执行push_back操作时,我期望内层的vetint能重新初始化、从头添加元素,但实际它会保留之前的值,导致元素重复累积。
示例代码
#include <iostream> #include <vector> using namespace std; class classe { public: int var; vector<int> vetint; }; int main() { vector<classe> vetor; classe obj; for (unsigned i=0; i<2 ; i++) { obj.var = (i+1)*10; for (unsigned c=0; c<3 ; c++) { obj.vetint.push_back((c+1)*100); } vetor.push_back(obj); } for (unsigned i=0; i < vetor.size() ; i++) { cout << "var(" << i << ") = " << vetor[i].var << endl; for (unsigned c=0; c < vetor[i].vetint.size() ; c++) { cout << "vetint(" << c << ") = " << vetor[i].vetint[c] << endl;; } } }
当前执行结果
var(0) = 10 vetint(0) = 100 vetint(1) = 200 vetint(2) = 300 var(1) = 20 vetint(0) = 100 vetint(1) = 200 vetint(2) = 300 vetint(3) = 100 vetint(4) = 200 vetint(5) = 300
期望输出结果
var(0) = 10 vetint(0) = 100 vetint(1) = 200 vetint(2) = 300 var(1) = 20 vetint(0) = 100 vetint(1) = 200 vetint(2) = 300
请问这个问题产生的原因是什么?该如何解决?
解答
问题原因
你只创建了一个classe对象obj,在整个循环过程中反复修改它的成员,然后把它的副本添加到外层vector里。但每次循环时,你没有清空obj.vetint,而是在之前的基础上继续push_back新元素,所以第二次循环时,vetint已经保留了第一次的3个元素,再加上新的3个就变成了6个,这个带有6个元素的对象被复制到外层vector后,就出现了元素累积的情况。
简单来说:你的obj是在循环外创建的,它的vetint容器不会自动重置,每次循环都是往同一个容器里追加元素。
解决方法
有几种实用的解决方式,你可以根据自己的需求选择:
方案1:每次循环创建新的classe对象
把classe obj;移到外层循环内部,这样每次循环都会生成一个全新的对象,它的vetint自然是空的,每次都能从头添加元素:
int main() { vector<classe> vetor; for (unsigned i=0; i<2 ; i++) { classe obj; // 每次循环新建对象,vetint默认是空的 obj.var = (i+1)*10; for (unsigned c=0; c<3 ; c++) { obj.vetint.push_back((c+1)*100); } vetor.push_back(obj); } // 输出部分保持不变 }
方案2:每次循环前清空obj.vetint
如果不想每次新建对象,可以在每次内层循环开始前,手动清空obj的vetint容器,确保每次都是从头添加元素:
int main() { vector<classe> vetor; classe obj; for (unsigned i=0; i<2 ; i++) { obj.var = (i+1)*10; obj.vetint.clear(); // 清空之前的元素,重置容器 for (unsigned c=0; c<3 ; c++) { obj.vetint.push_back((c+1)*100); } vetor.push_back(obj); } // 输出部分保持不变 }
方案3:给类添加构造函数(更规范的写法)
给classe添加一个构造函数,确保每次创建对象时成员都处于初始状态(虽然vector的默认构造已经会生成空容器,但显式定义构造函数能让代码更清晰,也方便后续扩展):
class classe { public: int var; vector<int> vetint; // 构造函数:初始化var为0,vetint默认是空容器 classe() : var(0) {} };
之后配合方案1使用,代码的可读性和规范性会更好。
内容的提问来源于stack exchange,提问作者Rogério Dec
相关产品推荐
相关产品推荐

