C ++ std :: vector条目的功能为NULL,但大小保持在零以上

时间:2019-06-06 09:43:19

标签: c++ vector iterator segmentation-fault

我用C / C ++编写代码已经有一段时间了,我已经找到解决问题的替代方法,但是我想知道为什么原始代码不起作用。

我有一个测试类,基本上只存储一个字符串。

class test {
private:
        std::string name;
public:
        test(std::string name) : name(name) {};
        std::string get_name() { return name; }
};

main中,我有一个向量,我在某一时刻用test对象填充。下面的代码模拟了向量vect的不规则用法。

int main(void) {
        std::vector<test *> vect;
        std::vector<test *>::iterator i;

        //* Comment this for a working example
        std::cout << "Searching empty vector" << std::endl;
        i = *(_is_in_vector(vect, std::string("test 3")));
        if (i == vect.end()) {
                std::cout << "Nothing found" << std::endl;
        } // */

        vect.push_back(new test("test 1"));
        vect.push_back(new test("test 2"));
        vect.push_back(new test("test 3"));

        std::cout << "All:" << std::endl;
        i = *(_is_in_vector(vect, std::string("test 3")));
        if (i != vect.end()) {
                std::cout << "Erase " << (*i)->get_name() << std::endl;
                vect.erase(i);
                delete *i;
        }

        i = *(_is_in_vector(vect, std::string("test 3")));
        if (i == vect.end()) {
                std::cout << "Nothing found" << std::endl;
        }

        std::cout << "Left:" << std::endl;
        for (i = vect.begin(); i!=vect.end(); ++i) {
                std::cout << (*i)->get_name() << std::endl;
                delete *i;
        }

        vect.clear();
        return 0;
}

由于在向量中搜索test对象多次,因此我创建了函数_is_in_vector,该函数搜索test对象并将迭代器返回给它。

static std::vector<test *>::iterator * _is_in_vector(std::vector<test *> &vect, std::string find) {
        std::string identity = find;
        static std::vector<test *>::iterator i = vect.begin();
        std::cout << "Vect size: " << vect.size() << std::endl;
        for (i; i != vect.end(); ++i) {
                std::string tmp = (*i)->get_name(); /* Segmentation fault after filling vector*/
                if (0 == identity.compare(tmp)) break;
        }
        return &i;
}

问题在于,当我注释掉Searching empty vector中的main部分时,上面的代码有效。一旦向量被test个对象填充,我将再次调用_is_in_vector。此函数中的向量确实具有三个条目,但是(*i)都指向NULL

输出:

Searching empty vector
Vect size: 0
Nothing found
All:
Vect size: 3
Segmentation fault

预期输出:

Searching empty vector
Vect size: 0
Nothing found
All:
Vect size: 3
Erase test 3
Vect size: 2
Nothing found
Left:
test 1
test 2

1 个答案:

答案 0 :(得分:5)

首先,不清楚为什么需要通过指针而不是通过值存储test对象。如果确实需要,请使用智能指针。

对于您的问题,为什么要返回指向迭代器的指针?这是您遇到问题的根本原因-使&i合法退还给您static,但static局部变量仅初始化一次,并且不会更改btw调用的值-因此先执行称它指向向量中的一个元素,但是之后您添加了元素并使所有迭代器(包括静态i)无效,这会导致分段错误。因此修复很简单-按值返回迭代器,并使i为非静态但规则的,这很轻巧,这样做是完全可以的。

_开头的PS标识符在全球范围内是非法的,有关详细信息,请参见What are the rules about using an underscore in a C++ identifier?

因此您的函数实际上应如下所示:

static std::vector<test *>::iterator  is_in_vector( std::vector<test *> &vect, const std::string &find) 
{
      return std::find_if( vect.begin(), vect.end(), [find]( test *p ) {
          return p->get_name() == find;
      } );
}

如果是这种情况或为了安全地将更改条件设置为以下条件,则假设向量永远不应该持有nullptr

          return p && p->get_name() == find;