从向量中擦除,通过引用传递
Erasing from a vector, passed by reference
我正在尝试通过索引从向量中删除元素,该索引已通过对某个函数的引用传递。通常,我会这样做:
void erase_element(vector<int> &my_vector, int index){
my_vector.erase(my_vector.begin() + index);
}
void make_vector(){
vector<int> my_vector = {1,2,3,4,5};
erase_element(my_vector, 3);
}
而且,事实上,为了检查我的理智,我 运行 这个并且它有效。
然而,出于某种原因,此 代码抛出 segfault
。有问题的行似乎是从向量 a1
、a2
和 a3
.
中删除元素的行
我的代码:
double maximum(double a, double b, double c)
{
return max(max(a, b), c);
}
double minimum(double a, double b, double c)
{
return min(min(a, b), c);
}
void findClosestTriplet(vector<double> &a1, vector<double> &a2, vector<double> &a3, TH2 *histo){
double res_min, res_max, res_mid;
int i = 0, j = 0, k = 0;
int a1Size = a1.size();
int a2Size = a2.size();
int a3Size = a3.size();
double diff = DBL_MAX;
while(i < a1Size && j < a2Size && k < a3Size){
double sum = a1[i] + a2[j] + a3[k];
double min = minimum(a1[i], a2[j], a3[k]);
double max = maximum(a1[i], a2[j], a3[k]);
if(min == a1[i]){
++i;
} else if (min == a2[j]){
++j;
} else {
++k;
}
if (diff > (max-min)){
diff = max - min;
res_max = max;
res_mid = sum - (max + min);
res_min = min;
}
}
a1.erase(a1.begin() + i); a2.erase(a2.begin() + j); a3.erase(a3.begin() + k);
}
void minimizer(){
TH2 *histo = new TH2D("Histo","Histo",1000,-0.1,0.1,1000,-0.1,0.1);
ROOT::RDataFrame f1("D","data1.root");
ROOT::RDataFrame f2("D","data2.root");
ROOT::RDataFrame f3("D","data3.root");
vector<double> a1,a2,a3;
a1.reserve(1E+6); a2.reserve(1E+6); a3.reserve(1E+6);
f1.Foreach([&](double tstamp){a1.push_back(tstamp);},{"UNIX"});
f2.Foreach([&](double tstamp){a2.push_back(tstamp);},{"UNIX"});
f3.Foreach([&](double tstamp){a3.push_back(tstamp);},{"UNIX"});
int maxiter = std::max(std::max(a1.size(), a2.size()), a3.size());
// std::ios_base::sync_with_stdio(false);
// std::cin.tie(NULL);
for(int i = 0; i < maxiter; ++i){
findClosestTriplet(a1,a2,a3,histo);
}
}
我试图制作一个最小的可重现示例,但失败了。 这个有效:
void findClosestTriplet(vector<double> &a1, vector<double> &a2, vector<double> &a3, TH2 *histo){
int i = 1; int j = 2; int k = 3;
a1.erase(a1.begin() + i); a2.erase(a2.begin() + j); a3.erase(a3.begin() + k);
}
void minimizer(){
TH2 *histo = new TH2D("Histo","Histo",1000,-0.1,0.1,1000,-0.1,0.1);
ROOT::RDataFrame f1("D","data1.root");
ROOT::RDataFrame f2("D","data2.root");
ROOT::RDataFrame f3("D","data3.root");
vector<double> a1,a2,a3;
a1.reserve(1E+6); a2.reserve(1E+6); a3.reserve(1E+6);
f1.Foreach([&](double tstamp){a1.push_back(tstamp);},{"UNIX"});
f2.Foreach([&](double tstamp){a2.push_back(tstamp);},{"UNIX"});
f3.Foreach([&](double tstamp){a3.push_back(tstamp);},{"UNIX"});
for(int i = 0; i < a1.size(); ++i){
findClosestTriplet(a1,a2,a3,histo);
std::cout << i << "\n";
}
histo->Draw("colz");
}
向量 a1
、a2
和 a3
在两种情况下都是相同的。整数 i,j,k
在循环之外,因此这似乎无关紧要。此外,我知道 i,j,k
在出错时不大于 a1,a2,a3
的大小,也不小于 0
的大小。
我知道我一定是在做一些蠢事。但是什么?
i
、j
或 k
之一将是其各自容器的大小。该元素的擦除调用将等效于 a.erase(a.begin() + a.size())
或 a.erase(a.end())
。传递给 erase
的迭代器必须有效且可取消引用。结束迭代器不可取消引用,不能传递给 erase
.
在 erase
调用中使用索引之前,您必须检查索引是否在范围内。
我正在尝试通过索引从向量中删除元素,该索引已通过对某个函数的引用传递。通常,我会这样做:
void erase_element(vector<int> &my_vector, int index){
my_vector.erase(my_vector.begin() + index);
}
void make_vector(){
vector<int> my_vector = {1,2,3,4,5};
erase_element(my_vector, 3);
}
而且,事实上,为了检查我的理智,我 运行 这个并且它有效。
然而,出于某种原因,此 代码抛出 segfault
。有问题的行似乎是从向量 a1
、a2
和 a3
.
我的代码:
double maximum(double a, double b, double c)
{
return max(max(a, b), c);
}
double minimum(double a, double b, double c)
{
return min(min(a, b), c);
}
void findClosestTriplet(vector<double> &a1, vector<double> &a2, vector<double> &a3, TH2 *histo){
double res_min, res_max, res_mid;
int i = 0, j = 0, k = 0;
int a1Size = a1.size();
int a2Size = a2.size();
int a3Size = a3.size();
double diff = DBL_MAX;
while(i < a1Size && j < a2Size && k < a3Size){
double sum = a1[i] + a2[j] + a3[k];
double min = minimum(a1[i], a2[j], a3[k]);
double max = maximum(a1[i], a2[j], a3[k]);
if(min == a1[i]){
++i;
} else if (min == a2[j]){
++j;
} else {
++k;
}
if (diff > (max-min)){
diff = max - min;
res_max = max;
res_mid = sum - (max + min);
res_min = min;
}
}
a1.erase(a1.begin() + i); a2.erase(a2.begin() + j); a3.erase(a3.begin() + k);
}
void minimizer(){
TH2 *histo = new TH2D("Histo","Histo",1000,-0.1,0.1,1000,-0.1,0.1);
ROOT::RDataFrame f1("D","data1.root");
ROOT::RDataFrame f2("D","data2.root");
ROOT::RDataFrame f3("D","data3.root");
vector<double> a1,a2,a3;
a1.reserve(1E+6); a2.reserve(1E+6); a3.reserve(1E+6);
f1.Foreach([&](double tstamp){a1.push_back(tstamp);},{"UNIX"});
f2.Foreach([&](double tstamp){a2.push_back(tstamp);},{"UNIX"});
f3.Foreach([&](double tstamp){a3.push_back(tstamp);},{"UNIX"});
int maxiter = std::max(std::max(a1.size(), a2.size()), a3.size());
// std::ios_base::sync_with_stdio(false);
// std::cin.tie(NULL);
for(int i = 0; i < maxiter; ++i){
findClosestTriplet(a1,a2,a3,histo);
}
}
我试图制作一个最小的可重现示例,但失败了。 这个有效:
void findClosestTriplet(vector<double> &a1, vector<double> &a2, vector<double> &a3, TH2 *histo){
int i = 1; int j = 2; int k = 3;
a1.erase(a1.begin() + i); a2.erase(a2.begin() + j); a3.erase(a3.begin() + k);
}
void minimizer(){
TH2 *histo = new TH2D("Histo","Histo",1000,-0.1,0.1,1000,-0.1,0.1);
ROOT::RDataFrame f1("D","data1.root");
ROOT::RDataFrame f2("D","data2.root");
ROOT::RDataFrame f3("D","data3.root");
vector<double> a1,a2,a3;
a1.reserve(1E+6); a2.reserve(1E+6); a3.reserve(1E+6);
f1.Foreach([&](double tstamp){a1.push_back(tstamp);},{"UNIX"});
f2.Foreach([&](double tstamp){a2.push_back(tstamp);},{"UNIX"});
f3.Foreach([&](double tstamp){a3.push_back(tstamp);},{"UNIX"});
for(int i = 0; i < a1.size(); ++i){
findClosestTriplet(a1,a2,a3,histo);
std::cout << i << "\n";
}
histo->Draw("colz");
}
向量 a1
、a2
和 a3
在两种情况下都是相同的。整数 i,j,k
在循环之外,因此这似乎无关紧要。此外,我知道 i,j,k
在出错时不大于 a1,a2,a3
的大小,也不小于 0
的大小。
我知道我一定是在做一些蠢事。但是什么?
i
、j
或 k
之一将是其各自容器的大小。该元素的擦除调用将等效于 a.erase(a.begin() + a.size())
或 a.erase(a.end())
。传递给 erase
的迭代器必须有效且可取消引用。结束迭代器不可取消引用,不能传递给 erase
.
在 erase
调用中使用索引之前,您必须检查索引是否在范围内。