Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the member variable passed to a function modified?

Tags:

c++

class

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.

like image 539
Apple Avatar asked Jan 29 '13 16:01

Apple


2 Answers

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.

like image 67
Bartek Banachewicz Avatar answered Oct 05 '22 23:10

Bartek Banachewicz


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))
{
   // ...
}
like image 43
Chad Avatar answered Oct 05 '22 23:10

Chad