Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Using const and references
Index -> Programming, C++ -> C++ Tutorials
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
wtd




PostPosted: Wed Mar 30, 2005 12:34 am   Post subject: Using const and references

When we pass parameters in C++, by default we make a copy of the thing we're passing in. There are a few practical problems with this:

For one, we can't make changes to that variable passed in. If I have:

code:
void read(int a)
{
   std::cin >> a;
}

int main()
{
   int foo = 42;

   read(foo);

   return 0;
}


Then I haven't actually changed foo at all from its initial value of 42.

The other problem is that passing by value means using memory, and CPU time is spent copying data around.

The solution?

References. We add a little & to the end of the type name and now we have not the value of the variable, but the variable itself.

code:
void read(int& a)
{
   std::cin >> a;
}

int main()
{
   int foo = 42;

   read(foo);

   return 0;
}


Eureka! It works. Now we've tackled the problem of pass-by-value.

This also solves the problem of lots of memory being copied. It raises another problem though. Now we can make changes to the variable being passed in. Sometimes we distinctly do not want to do this.

Let's create a basic Name class with a friend operator for output.

code:
class Name
{
   private:
      std::string first, last;
   public:
      Name(std::string f, std::string l) : first(f), last(l) { }
   
      friend std::ostream& operator<<(std::ostream& out, Name& n);
};

std::ostream& operator<<(std::ostream& out, Name& n)
{
   out << n.first << " " << n.last;
   n.first = "Wooble!";
   return out;   
}

int main()
{
   Name bobs_name("Bob", "Smith");

   std::cout << bobs_name << std::endl;   
   std::cout << bobs_name << std::endl;

   return 0;
}


Whoa! What's this? The two are not the same. This is because the output operator changed the name. That doesn't make any sense.

To avoid this (or at least make the compiler complain about it), use the const keyword.

code:
class Name
{
   private:
      std::string first, last;
   public:
      Name(std::string f, std::string l) : first(f), last(l) { }
   
      friend std::ostream& operator<<(std::ostream& out, const Name& n);
};

std::ostream& operator<<(std::ostream& out, const Name& n)
{
   out << n.first << " " << n.last;
   return out;   
}

int main()
{
   Name bobs_name("Bob", "Smith");

   std::cout << bobs_name << std::endl;   
   std::cout << bobs_name << std::endl;

   return 0;
}


This now works fine, and had I left the assignment in there, it would not have compiled at all.

But, let's say we have a full_name method which generates the string to output.

code:
class Name
{
   private:
      std::string first, last;
   public:
      Name(std::string f, std::string l) : first(f), last(l) { }

      std::string full_name()
      {
         return first + " " + last;
      }
   
      friend std::ostream& operator<<(std::ostream& out, const Name& n);
};

std::ostream& operator<<(std::ostream& out, const Name& n)
{
   out << n.full_name();
   return out;   
}


Now, what's wrong here? Well, I can't call the full_name function from within a "const" environment. But, you should protest, "full_name doesn't change anything, so it should be fine!"

Well, you'd be right, but we never told the compiler that. Again, we use the const keyword.

code:
class Name
{
   private:
      std::string first, last;
   public:
      Name(std::string f, std::string l) : first(f), last(l) { }

      std::string full_name() const
      {
         return first + " " + last;
      }
   
      friend std::ostream& operator<<(std::ostream& out, const Name& n);
};

std::ostream& operator<<(std::ostream& out, const Name& n)
{
   out << n.full_name();
   return out;   
}


Now it's fine.
Sponsor
Sponsor
Sponsor
sponsor
Martin




PostPosted: Thu Mar 31, 2005 7:39 pm   Post subject: (No subject)

Always use const when you can.

When passing references to a function, if you don't plan on changing those values, you should make them constant.

So intead of
code:
int foo (int x) { }
you should have
code:
int foo (const int x) { }
Display posts from previous:   
   Index -> Programming, C++ -> C++ Tutorials
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 2 Posts ]
Jump to:   


Style:  
Search: