I'm still exploring C++ trying to figure out how it works and came across something that puzzles me.
I have a class that simply holds a list<string>
and has a few member functions
class String_list {
public:
String_list(istream&);
//other functions
list<string> listing;
};
and I wrote my constructor to use a non-member function
String_list::String_list(istream& in) { get_strings(in, listing); }
with
istream& get_strings(istream& in, list<string> lstring)
{
if(in) {
lstring.clear();
string word;
while (in >> word)
lstring.push_back(word);
in.clear();
}
return in;
}
The problem is, though the get_string
function seems to work, it doesn't change the listing
member variable I passed to it.
I can get it to work by making get_strings
a member function with one argument (istream& in)
by just changing lstring
to listing
, so I assume that either the passing of the list from the constructor doesn't work for some reason, or that the non-member function can't change the member-variable, but these seems like the sort of things my compiler would easily pick up on.
My compiler doesn't see any problem with the code it's just when I run the executable that the member list always has .size()
of 0.
You should pass lstring
by reference:
istream& get_strings(istream& in, list<string>& lstring)
The code compiles and works as it is written : passing the value of lstring, thus copying it. All the changes are made on a temporary object, then discarded when the object is destroyed.
You're passing a copy of your member variable to the function. The local copy is modified, while the member variable is not.
Change the signature of your get_strings
function to take a reference to your list object and this will work:
istream& get_strings(istream& in, list<string>& lstring)
{
// ...
}
Though this breaks encapsulation, in your case (exposing directly the member variable to that function). A better method may be to have the get_strings
function return a copy of the list it populates, then assign it to your class's member in an initializer list. Like this:
list<string> get_strings(istream& in)
{
list<string> r;
// ...
return r;
}
Then your constructor:
StringList::StringList(istream& in) : listing(get_strings(in))
{
// ...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With