【发布时间】:2014-11-19 05:13:47
【问题描述】:
我想我对如何移动 STL 容器有一些误解 按值与按引用的对象。具体看不懂 为什么以下程序崩溃:
#include <vector>
#include <set>
#include <cstdio>
class Value {
public:
int x, y;
Value(int a, int b) { x = a; y = b; }
};
class Test {
public:
Test(int x, int y) { values.insert(new Value(x, y)); }
void add(int x, int y) { values.insert(new Value(x, y)); }
std::set<Value *> getValues() { return values; }
private:
std::set<Value *> values;
};
int main() {
std::vector<Test> Ts;
for (unsigned i = 0; i < 5; i++) {
Test t(0, 0);
t.add(i, 0);
Ts.push_back(t);
}
for (unsigned i = 0; i < 5; i++) {
for (std::set<Value *>::iterator it = Ts.at(i).getValues().begin(), ite = Ts.at(i).getValues().end(); it != ite; ++it) {
Value *v = *it;
printf("(%d, %d) ", v->x, v->y);
}
printf("\n");
}
return 0;
}
此程序在第二个 for 循环中出现段错误(试图打印
Ts 向量中的值)。但是,如果将初始循环更改为:
for (unsigned i = 0; i < 5; i++) {
Ts.push_back(Test(0, 0));
}
然后程序运行良好。此外,如果你采取第一个 程序(崩溃)并将打印循环更改为:
for (unsigned i = 0; i < 5; i++) {
std::set<Value *> values = Ts.at(i).getValues();
for (std::set<Value *>::iterator it = values.begin(), ite = values.end(); it != ite; ++it) {
Value *v = *it;
printf("(%d, %d) ", v->x, v->y);
}
printf("\n");
}
那么程序就不会崩溃了。
我想了解导致这些崩溃的原因,以及程序之间的区别。
【问题讨论】:
-
您知道您的程序正在泄漏内存吗?绝对没有理由在
Test类中使用new。 -
@pmr 是的。这是我的大型程序的简化测试用例版本,稍后会正确释放值。
-
除了您泄漏内存的部分之外,您还制作了 for 循环中设置的
values的多个副本,因为getValues()返回一个副本。这可能是迭代器在内存中到达错误位置并导致分段错误的原因。 -
@E_net4 至少,那些迭代器可能不会被比较,它们指向不同的对象(数据结构)。
it指向的范围的结尾是 notite。
标签: c++ memory-management stl pass-by-reference pass-by-value