迭代器取消引用中的分段错误
Segmentation fault in iterator dereferencing
下面列出的代码在基于迭代器的循环中触发分段错误:
#include <iostream>
#include <vector>
class A {
public:
A(unsigned id = 0) {id_ = id;}
unsigned get_id() {return id_;}
private:
unsigned id_;
};
class B {
public:
B() {}
B(std::vector<A*> entries) : entries_(entries) {}
const std::vector<A*> get_entries() const {
return entries_;
}
private:
std::vector<A*> entries_;
};
int main() {
std::vector<A*> entries;
for (unsigned i = 0; i < 5; i++) {
entries.push_back(new A(i));
}
B b(entries);
// index based access (ok)
for (unsigned i = 0; i < b.get_entries().size(); i++) {
std::cout << b.get_entries()[i]->get_id() << std::endl;
}
// iterator based access (segmentation fault)
for (std::vector<A*>::const_iterator i = b.get_entries().begin();
i != b.get_entries().end();
++i) {
std::cout << (*i)->get_id() << std::endl;
}
}
另一方面,基于索引的循环工作正常。
当返回 std::vector
的副本(参见:const std::vector<A*> get_entries() const
)而不是对它的 const
引用时,会触发此行为,例如const std::vector<A*>& get_entries() const
。
后一种情况效果很好。
如何解释这种行为?
问题是 get_entries
return 是矢量的临时副本,而不是对原始文件的引用。因此,每次您调用它并将迭代器获取到临时 return 值时,该迭代器将在您开始使用它时失效。这会导致未定义的行为,其中崩溃很常见。
这里有两个选择。
选项 1:将 returned 向量存储在局部变量中并对其进行迭代。
方案二:修改函数为return引用const std::vector<A*> & get_entries() const
.
由于 get_entries()
returns 一个向量值,你每次都使用不同的 std::vector<A*>
对象。比较来自不同向量的迭代器是未定义的行为,所以即使只有 get_entries().begin() != get_entries().end()
你已经有麻烦了。
下面列出的代码在基于迭代器的循环中触发分段错误:
#include <iostream>
#include <vector>
class A {
public:
A(unsigned id = 0) {id_ = id;}
unsigned get_id() {return id_;}
private:
unsigned id_;
};
class B {
public:
B() {}
B(std::vector<A*> entries) : entries_(entries) {}
const std::vector<A*> get_entries() const {
return entries_;
}
private:
std::vector<A*> entries_;
};
int main() {
std::vector<A*> entries;
for (unsigned i = 0; i < 5; i++) {
entries.push_back(new A(i));
}
B b(entries);
// index based access (ok)
for (unsigned i = 0; i < b.get_entries().size(); i++) {
std::cout << b.get_entries()[i]->get_id() << std::endl;
}
// iterator based access (segmentation fault)
for (std::vector<A*>::const_iterator i = b.get_entries().begin();
i != b.get_entries().end();
++i) {
std::cout << (*i)->get_id() << std::endl;
}
}
另一方面,基于索引的循环工作正常。
当返回 std::vector
的副本(参见:const std::vector<A*> get_entries() const
)而不是对它的 const
引用时,会触发此行为,例如const std::vector<A*>& get_entries() const
。
后一种情况效果很好。
如何解释这种行为?
问题是 get_entries
return 是矢量的临时副本,而不是对原始文件的引用。因此,每次您调用它并将迭代器获取到临时 return 值时,该迭代器将在您开始使用它时失效。这会导致未定义的行为,其中崩溃很常见。
这里有两个选择。
选项 1:将 returned 向量存储在局部变量中并对其进行迭代。
方案二:修改函数为return引用const std::vector<A*> & get_entries() const
.
由于 get_entries()
returns 一个向量值,你每次都使用不同的 std::vector<A*>
对象。比较来自不同向量的迭代器是未定义的行为,所以即使只有 get_entries().begin() != get_entries().end()
你已经有麻烦了。