C++:向量“损坏”的第一个元素

Posted

技术标签:

【中文标题】C++:向量“损坏”的第一个元素【英文标题】:C++: First element of vector "corrupting" 【发布时间】:2009-05-13 05:23:53 【问题描述】:

我有一个包含向量的类 (foo)。

如果我尝试像这样迭代向量中的元素:

for(vector<random>::iterator it = foo.getVector().begin();
        it != foo.getVector().end(); ++it) 
  cout << (*it) << endl;


第一个元素总是损坏并返回垃圾数据。

但是,如果执行以下操作:

 vector<random> v = foo.getVector();
 for(vector<random>::iterator it = v.begin();
            it != v.end(); ++it) 
      cout << (*it) << endl;

 

一切似乎都运行良好。有没有我不知道的“陷阱”?

我也尝试过 cout

谢谢。

编辑:

这是我的头文件:

#ifndef HITS
#define HITS

#include <vector>
#include "wrappers.h"

class Hits 

    public:
        Hits();
        std::vector<word_idx_value> getVector() return speech_hits;
        const std::vector<word_idx_value> getVector() const return speech_hits;
        void add(const word_idx_value&);
        Hits &operator+=(const Hits&);
    private:
        std::vector<word_idx_value> speech_hits;
;

#endif

【问题讨论】:

我们可以看看你的 getVector() 成员函数吗?也许有什么东西在那里修改了它? 什么返回 getVector() ?它是矢量的副本还是对存储在其他地方的现有矢量的引用? 我已将其更改为按引用而不是按值返回。它似乎工作正常,但为什么按值传递会对结果产生如此大的影响? 因为迭代器的两个边界完全不相关(尽管内容相同)。这就像 char foo[6] = "Hello"; char *bar = malloc(sizeof(char) * 6); strcat(酒吧,富); for(char *p = foo; p 应该影响更大。您返回一个副本,您将获得一个迭代器。返回的值(临时)永远不会存储,因此在下一句中将其删除。现在,您正在使用迭代器进入无人区。分段错误可能是第一次访问或第二次访问的结果,或者当循环尝试匹配不同向量的 end() 迭代器时......阅读 GoTW 18:gotw.ca/gotw/018.htm 【参考方案1】:
for(vector<random>::iterator it = foo.getVector().begin();

当您执行foo.getVector() 时会返回临时向量,并在foo.getVector().begin(); 之后遇到; 时将其销毁因此迭代器在循环内变得无效。

如果将foo.getVector(); 的值存储在向量v (v = foo.getVector();) 中,然后使用向量v,它就可以正常工作。这是因为向量 v 在整个循环中都是有效的。

【讨论】:

没错。但请注意,即使像 std::copy(foo.getVector().begin(), foo.getVector().end(), dest) 这样的东西也有未定义的行为(如我的回答),即使两个临时向量都存在直到std::copy 返回。 是的。正如你提到的,它是向量的两个副本,迭代器是不同的。【参考方案2】:

getVector() 按值返回一个向量。 getVector 的两次调用(begin() 和 end())返回向量的不同副本,因此您在一个对象上调用 begin(),在另一个对象上调用 end()。你得到的是两个迭代器进入两个不同的容器。将这两个迭代器与 != 进行比较会产生一个未定义的值。

【讨论】:

【参考方案3】:

getVector() 按值返回向量,在第一种情况下,您会得到一个临时变量,一旦进入循环,该变量就会被销毁。在第二种情况下,您将结果复制到在循环内仍然存在的局部变量中。可能的解决方案是通过 const 引用返回向量。

【讨论】:

【参考方案4】:

您的错误在 getVector() 方法中。 通过引用返回。

class Hits

    public:
    std::vector<word_idx_value>&   getVector() return speech_hits;
    //                         ^
    //                      Add the & to return by reference.

    // You may also want a const version at some point.
    std::vector<word_idx_value> const&   getVector() const return speech_hits;

如果您不通过引用返回,则您正在创建一个临时副本。副本在使用后被销毁。在这种情况下,在 begin() 执行后临时对象被销毁,因此 begin() 返回的迭代器无效。

【讨论】:

【参考方案5】:

修改 getVector 函数以返回对象引用,如下所示: std::vector& getVector() return speech_hits;

【讨论】:

以上是关于C++:向量“损坏”的第一个元素的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中检索矩阵的每个向量的第一个元素?

在 C++ 中并行查找向量的第一个

查找向量中的第一个缺失元素

C++ 合并和排序 2 个向量

堆栈/堆中的向量元素?长输入,C++

从特定的第一个元素获取向量对的第二个元素