Reputation: 55
I'm kinda new to C++, and I have a question that I am curious about. For a while I was getting segmentation faults, though I did eventually make it work, but I would like to know why it wasn't before. This is what I had:
#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;
}
And I solved my problem by replacing every instance of this->getList()
with this->list
(there were 3; one in B::addA(A*)
and two in the for loop definition in B::as_a_string()
). Why would using the member itself instead of accessing it through a method affect the workings of this program?
Upvotes: 2
Views: 85
Reputation: 537
Your code:
class B {
private:
vector<A*> list;
public:
vector<A*> getList(){return this->list;}
void addA(A* i){this->getList().push_back(i);}
is calling push_back() on a temporary because getList() returns by value. After calling add(), the member variable list is unchanged. You can change your getList() function signature to return a reference like this:
vector<A*>& getList(){return this->list;}
Honestly, you probably are better off with the solution that you used to avoid the problem because providing a public accessor that returns a reference to your implementation details is something you would generally want to avoid.
Upvotes: 2
Reputation: 20838
The problem is that your B::getList()
returns list by value and so a copy of B::list
is actually returned rather than the original list itself.
In your loop here:
for (vector<A*>::iterator x = this->getList().begin();
x != this->getList().end(); ++x)
You start by getting a begin iterator to this temporary list. Everytime the condition is checked, you are comparing it to the end iterator to a different temporary list object.
The easy fix for this is to have B::getList()
return the list by reference:
vector<A*>& getList();
Upvotes: 2
Reputation: 129364
Since getList
is returning a temporary copy of list
, the list
is gone again when you try to iterate through it.
There are a few different ways to deal with this:
list
(no need to use this->
- it is not PHP, Python or some such language where you always have to refer to members via the this
/self
pointer). getList
return a reference to the vector. (vector<A*>& getList() { ... };
)However, option 3, that won't help in addA
, which requires that you operati on the ORIGINAL list - as it stands, your push_back
operate on a temporary copy of list
, which is immediately destroyed afterpush_back
returns - so it doesn't actually add anything at all to the actual list
member variable).
Personally, I would change your internal code to use list
directly, and keep getList
returning a copy, so that if some external function wants to get hold of the list, it can.
Edit: You are also leaking memory by not deleing the A* and B* objects that you create in main
.
Upvotes: 2