操作检索到的矢量时的分段错误

时间:2013-08-13 23:46:53

标签: c++ class vector segmentation-fault

我是C ++的新手,我有一个我很好奇的问题。有一段时间我得到了分段错误,虽然我最终确实有效,但我想知道为什么它不是之前。这就是我所拥有的:

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
class A {
    private:
        int num;
    public:
        A(int i){this->num=i;}
        int getNum(){return this->num;}
};
class B {
    private:
        vector<A*> list;
    public:
        vector<A*> getList(){return this->list;}
        void addA(A* i){this->getList().push_back(i);}
        string as_a_string(){
            stringstream result;
            cout << "Flag1" <<endl; //only for debug, this prints
            for (vector<A*>::iterator x = this->getList().begin(); x != this->getList().end(); ++x) {
                cout << "Flag2" << endl; //only for debug, this prints
                A* w = *x;
                cout << "Flag3" << endl; //only for debug, this prints
                result << w->getNum() << " ";
                cout << "Flag4" << endl; //only for debug, this does not print
            }
            return result.str();
        }
};
int main() {
    A* a = new A(4);
    B* b = new B();
    b->addA(a);
    cout << b->as_a_string() << endl;
    return 0;
}

我通过用this->getList()替换this->list的每个实例解决了我的问题(B::addA(A*)中有3个; B::as_a_string()中的for循环定义中有2个) 。为什么使用成员本身而不是通过方法访问它会影响该程序的工作?

3 个答案:

答案 0 :(得分:2)

由于getList正在返回list的临时副本,因此当您尝试迭代list时,list会再次消失。

有几种不同的方法可以解决这个问题:

  1. 只需使用this->(无需使用this - 它不是PHP,Python或某些此类语言,您始终必须通过self / {{1来引用成员指针)。
  2. getList返回对向量的引用。 (vector<A*>& getList() { ... };
  3. 使用本地变量作为副本
  4. 但是,选项3(addA无效,需要您在原始列表中操作 - 按原样,push_back操作list的临时副本},在push_back返回后立即销毁 - 所以它实际上并没有向实际的list成员变量添加任何内容。)

    就个人而言,我会更改您的内部代码以直接使用list,并保持getList返回副本,这样如果某些外部函数想要获取列表,它就可以。

    编辑:您还通过不删除在main中创建的A *和B *对象来泄漏内存。

答案 1 :(得分:2)

问题是您的B::getList()按值返回列表,因此实际返回B::list的副本而不是原始列表本身。

在你的循环中:

for (vector<A*>::iterator x = this->getList().begin();
     x != this->getList().end(); ++x)

首先获取此临时列表的开始迭代器。每次检查条件时,都要将它与结束迭代器与不同的临时列表对象进行比较。

对此的简单修复是让B::getList()通过引用返回列表:

vector<A*>& getList();

答案 2 :(得分:2)

您的代码:

class B {
    private:
        vector<A*> list;
    public:
        vector<A*> getList(){return this->list;}
        void addA(A* i){this->getList().push_back(i);}

在临时调用push_back()因为getList()按值返回。调用add()后,成员变量列表保持不变。您可以更改getList()函数签名以返回如下引用:

vector<A*>& getList(){return this->list;}

老实说,您可能最好使用以前解决问题的解决方案,因为提供一个公共访问器可以返回对实现细节的引用,这是您通常希望避免的。