Apple
Apple

Reputation: 351

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

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.

Upvotes: 5

Views: 434

Answers (3)

Piotr Chojnacki
Piotr Chojnacki

Reputation: 6857

In C++ you're passing by value, not by reference unless you do it explicitly. So if you declare your function:

istream& get_strings(istream& in, list<string> lstring) 

then lstring is passed by value, which means that you're not using the same object you're passing in a function call. You simply make a copy of this object and even though you modify it in a function body, you only modify this copy.

If you want to modify an object which you pass, you should pass it by reference, which you can achieve by using &:

istream& get_strings(istream& in, list<string>& lstring) 

Upvotes: 4

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39370

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.

Upvotes: 10

Chad
Chad

Reputation: 19032

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))
{
   // ...
}

Upvotes: 9

Related Questions