迭代器解除引用

时间:2015-11-30 21:29:15

标签: c++ vector reference iterator dereference

下面列出的代码在基于迭代器的循环中触发了分段错误:

#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。 后一种情况很好。

如何解释这种行为?

2 个答案:

答案 0 :(得分:2)

由于get_entries()按值返回向量,因此您每次都使用不同的std::vector<A*>对象。比较来自不同向量的迭代器是未定义行为,因此即使只有get_entries().begin() != get_entries().end(),您也已经遇到了麻烦。

答案 1 :(得分:1)

问题是get_entries返回向量的临时副本,而不是对原始的引用。因此,每次调用它并将迭代器捕获到临时返回值时,该迭代器在您使用它时将无效。这导致了未定义的行为,其中崩溃非常常见。

这里有两个选择。

选项1:将返回的矢量存储在局部变量中并对其进行迭代。

选项2:修改函数以返回引用const std::vector<A*> & get_entries() const