On 25/05/2007, at 12:48 AM, Michael Chesterton wrote:

When passing an array as an argument to a function, say, print_foo,
where the function isn't meant to modify the array, it makes perfect
sense to me to make it a const.

The C++ FAQ Lite has a section devoted to const correctness:

  http://www.parashift.com/c++-faq-lite/const-correctness.html

It's an invaluable resource to bookmark if you do any C++ coding.

But what about when passing structs, ints, bools, etc? If the function
doesn't need to modify them, what's the standard practice?

I guess an example. (hopefully if I've ERRORED, my intent is still
clear)

struct foo
{
  int x;
  int y;
};

void init(foo &p, const int x, const int y)
{
  p.x = x;
  p.y = y;
}

Do people do that in practice? Is it good practice?

Most people don't bother using const for function parameters that are primitives (ints, bools, char, etc). I still do, since I think it's good documentation: it indicates you never intend to modify it in the function, and frees up your mental stack to track something else.

If you're passing a large structure to a function, the standard C++ idiom is to pass a const reference rather than pass the structure by value, so instead of this:

  void foo(my_large_structure_t bar);

do this:

  void foo(const my_large_structure_t& bar);

Using a reference prevents a copy of the large structure, which can be relatively expensive. Using a const reference means that you can't change the original structure, so it gives more similar semantics to pass-by-value. It also theoretically enables more optimisation opportunities, although in practice it's not a big win.

You can also use const references for primitive types too (e.g. const int& foo), but that's not done because it's generally a performance loss, and it also looks weird :).

Personal opinion: I go so far as to declare all my local variables as const, and will sometimes restructure code to ensure that const is used on as many variables as possible. I actually wish that C++09 would have a compiler flag to enforce const being the default, and that you'd have to put the keyword 'mutable' in front of variables you want to change :). (My Haskell background is showing here...) Using const heavily makes reading and grokking the code much easier, IMHO.

There's two more issues with const. For pointers, you can have "const Foo* p", meaning that the value of the p pointer can change, but the value that p points to is const; "Foo* const p", which means that the p pointer is const but that you can change the Foo value that p points at; and "const Foo* const p", meaning both. "Foo* const p" is similar in spirit to a reference, since you cannot "reseat" the pointer. "const Foo* const p" is similar to a const&.

There's also const member functions, which means that the member function cannot change the object's member variables. They're usually used with accessors:

  class Foo
  {
  public:
    // Note the const qualifier after the function prototype below
    int getX() const
    {
      return x;
    }

    void setX(const int newX)
    {
      x = newX;
    }

  private:
    int x;
  }

See the C++ FAQ lite for more information, it's really a superb resource.

Oh yeah, and there's also const_iterators that you can use in place of iterators (const_iterator it = map.begin(); ...).


--
% Andre Pang : trust.in.love.to.save  <http://www.algorithm.com.au/>



_______________________________________________
coders mailing list
[email protected]
http://lists.slug.org.au/listinfo/coders

Reply via email to