Skip to main content
GameDev.net gamedev.net
🔒 Locked

Q: C++ const &

Started by glaskows Dec 12, 2004 at 10:37 PM 12 replies 2k views
Original Post
glaskows
glaskows
Should i use "const type &some_var" every time I am passing an argument wich isn't gonna be modified later inside the function?... and why? Thanks in advance.
Oluseyi
Oluseyi
Yes. const correctness is a way of enforcing design by contract and helping to mitigate unintentional errors. Since non-const methods can not be called on a const object/reference, it is a means of validating post-conditions, something C++ doesn't have much of.

Furthermore, passing by const reference allows for the use of literals, which are inherently constant.
Drew_Benton
Drew_Benton
Also yes if you are passing User Data Types to save memory, if you have a 100byte class, everytime you pass it in a paramer not using a & or *, it will create a copy-constructed value. This takes time and memory space, but is elimiated when you use const & or * (a pointer) to the UDT.
uavfun
uavfun
For simple types such as int, bool, float, etc. there is no need to use a reference; ordinary pass-by-value is just fine. You may mark them with const but this is of relatively limited use - it won't have an effect on code that calls the function; it only stops you from modifying the parameter inside the function (which has no effect on whatever was originally passed to it).
kaysik
kaysik
Quote:
Original post by uavfun
You may mark them with const but this is of relatively limited use - it won't have an effect on code that calls the function; it only stops you from modifying the parameter inside the function (which has no effect on whatever was originally passed to it).


Except if you have a const variable you want to pass into the function! Also its a sign to the caller that their data won't be touched and should be used when ever possible. Its no hassle to type the extra 6 characters needed for const (remembe the space :D) and it adds quite a bit. So while it may not have any direct affect on the data it helps in many other ways.
IndigoDarkwolf
IndigoDarkwolf
Quote:
Original post by kaysik
Except if you have a const variable you want to pass into the function!


Well, uavfun was referring to native types, such as int, unsigned int, char, double, float, etc. These types are so small that there is usually no (or almost no) penalty for passing them by-value. Further, they have default operators defined to copy their values from a const type to a non-const type, so the following code really does work:

void foo(int a){  cout << a << endl;}void bar(){  const int c = 45;  foo(c);}


This works for any single native type, but I don't believe it works for arrays or pointers (not sure).

"const" also has more uses than protecting a pass-by-reference variables from being modified. There are three uses for const:

/* this usage prevents an argument from being modified within the function. */void foo(const int);/* this usage prevents a function from modifying other members of the class. */class bar {private:  // (Add some member variables here)public:  void foo(int) const;}/* similar to the first example, this usage prevents the return value of the function from being modifed. */const int func();


Const correctness falls under those "good programming practices", just like using the tab key to indent blocks of code and never using globals. As I've stated in other posts, I'm typically not a fan of "good programming" where pure education is concerned. I would, however, still recommend (insist, even) that you use const in all of your other non-educational programming projects, most especially professional ones.

Hope that helps. :)
ajas95
ajas95
'const' is especially useful when you're working with other people on a project. With a const-correct code base, you just need to look at a function's signature... if an argument is passed by a non-const reference, you should expect that that variable will be modified.

If the codebase is not const-correct, then you'd have to scan through the code of the function you're calling to see if the variable you pass in by reference gets modified anywhere (a *huge* pain).

Note that because of the situation Kaysik describes, starting to 'const' variables has a viral effect on your codebase. You have to keep adding consts all over the place until it will finally compile again. But you'll have a much better code-base in the long run. If it doesn't change, MAKE IT CONST! :)

[edit]
IndigoDarkWolf: the situation Kaysik was describing, to use your example, would require instead:
 void foo(int& a) 

I know you'd say 'well that is pointless', which may be true... however I believe the OP question meant "Should I pass by reference or const reference?" not "Should I pass by const reference or by value?"

and anyway, the only way the code above makes sense is if a were to be modified by foo, right?
[/edit]
Spudder
Spudder
Herb Sutter has two atricles on his Guru Of The Week site, one on const correctness which gives guidelines on how and when to use const and another on how effective const is in producing optimised code. Both are well worth a read to get an idea of proper const-correctness.
Qw3r7yU10p!
Qw3r7yU10p!
Quote:
Original post by Spudder
Herb Sutter has two atricles on his Guru Of The Week site, one on const correctness which gives guidelines on how and when to use const and another on how effective const is in producing optimised code. Both are well worth a read to get an idea of proper const-correctness.


What he said.
Oluseyi
Oluseyi
Quote:
Original post by IndigoDarkwolf
Quote:
Original post by kaysik
Quote:
Original post by uavfun
You may mark them with const but this is of relatively limited use - it won't have an effect on code that calls the function; it only stops you from modifying the parameter inside the function (which has no effect on whatever was originally passed to it).
Except if you have a const variable you want to pass into the function!
Well, uavfun was referring to native types, such as int, unsigned int, char, double, float, etc. These types are so small that there is usually no (or almost no) penalty for passing them by-value.
*Ahem* Literals. The only way to support both the efficient passing of arbitrarily-sized objects and literal parameters is via constant reference.
void SomeFunction(std::string s);void SomeOtherFunction(const & std::string s);...std::string str;...SomeFunction(str);                 // OkaySomeFunction("Some String");       // Blows up, or necessitates construction of temporary object and copyingSomeOtherFunction(str);            // OkaySomeOtherFunction("Some String");  // Okay
glaskows
glaskows
Thanks for the replies.
About the article const correctness I didn't quite understand why the author declared "CalcArea()" as a const member function when, in fact, it does change the member variable "area_".
GotW is going right to my bookmarks :)
Qw3r7yU10p!
Qw3r7yU10p!
Quote:
Original post by glaskows

Thanks for the replies.

About the article const correctness I didn't quite understand why the author declared "CalcArea()" as a const member function when, in fact, it does change the member variable "area_".

GotW is going right to my bookmarks :)

area_ is an implementation detail and shouldn't concern users of the class.

When GetArea is called, if the area hasn't already been calculated, it calculates it. So a function (GetArea), which you wouldn't expect to modify the object, does actually modify it, if necessary, through calling CalcArea. So area_ is made mutable. This means the functions can be const but can modify the member (i.e. mutate it)
Enigma
Enigma
Quote:
Original post by glaskows
Thanks for the replies.
About the article const correctness I didn't quite understand why the author declared "CalcArea()" as a const member function when, in fact, it does change the member variable "area_".
GotW is going right to my bookmarks :)


This is the argument between bitwise constness (do any of the members change) and conceptual constness (does the external view of the object change). Although the area_ member is calculated in this member function it does not change the conceptual constness of the object. A polygon's area does not change when you calculate the area, only when you change the positions of the corners. Additionally it would be fully possible to eliminate the area_ member variable entirely and simply recalculate the area each time it is requires, enabling the member function to be truly bitwise const. Storing the calculated area in area_ is just an optimisation. area_ simply caches the value in order to eliminate redundant calculations if the area is requested again.

Enigma
mishikel
mishikel
I'll echo Enigma. const-ness of functions should follow observable state. hence the mutable keyword.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.