C++ const Correctness
Even thorough this article is titled "C++ const Correctness", we're not going to talk about const yet. Instead, we're going to start by talking about functions and their parameters. Consider the following class and function:
class Invoice {
public:
//...
protected:
std::vector<Item> items;
};
void f( Invoice i );
The consequence of calling f() includes the cost of making a copy of the Invoice object. You suffer this consequence because f() is declared to take its parameter by value. If the Invoice class is anything other than a trivial class, this can be an expensive and slow operation. In this case, the std::vector<Item> member variable could potentially have hundreds of items or more, all of which need to be copied when Invoice objects are passed by value. Further, passing objects by value might result in object "slicing", wherein the compiler generates code only to copy the Invoice object. If Invoice happened to be a polymorphic class, all the information in derived classes would be lost. For example:
class Invoice {
public:
virtual ~Invoice();
virtual int sum();
//...
protected:
std::vector<Item> items;
};
class CustomerInvoice : public Invoice {
public:
virtual int sum();
// ...
protected:
std::vector<CustomerItem> custItems;
};
CustomerInvoice c;
f( c ); // oops: sliced
In this example, the CustomerInvoice is copied by value. Because f() is declared to take an Invoice, the compiler slices off the CustomerInvoice parts of the object, leaving f() with potentially misleading information. The Invoice::sum() member function is not called polymorphically within f()--this is a design error. In general, copying user-defined types by value should be avoided because of these problems.
You can solve this problem, however, by rewriting f() like this: void f( Invoice* i );. Here, f() is declared to take a pointer to an Invoice. This avoids copying Invoices by value--only the value of the pointer is copied--and also avoids the "slicing" problem. However, passing parameters by pointer shifts an additional burden onto f(): the function needs to protect itself from null pointers. It is much better to declare f() like this, void f( Invoice& i );. Here, Invoice is passed by reference. This also speeds things up tremendously, because only the address of the Invoice object is passed instead of a copy of the entire Invoice object. You never can create an invalid reference, so f() does not need to worry about invalid pointers. Slicing also is avoided, and f() now is able to exploit safely the polymorphic nature of Invoice. For example, f() may be defined as follows:
void f( Invoice& i ) {
int s = i.sum(); // calls correct member function
//...
}
Even though passing by reference gives a huge speed boost compared to passing by value, you shouldn't be satisfied yet. The function f() suffers from another design error. Once the function f() is called, it has access to all the public member functions of Invoice, allowing it to modify the value of the Invoice object which was passed to it. This often is less than desirable. For example, f() may be defined like this:
void f( Invoice& i ) {
int s = i.sum();
i.giveDiscount( s/2 ); // oops: modifies the invoice
//...
}
The entire public interface of Invoice is available, so f() is able to make some potentially unwanted modifications to the Invoice object. It would be better to get the speed benefits of passing user defined objects by reference and also limit the interfaces of those objects so that their internal state cannot be altered. More often than not, functions want to read the values of their parameters, not alter them--and especially not alter parameters passed by reference, as those values typically belong to the calling object or function that may not be expecting such underhandedness. And here's where const comes in. The function f() can be declared to take a constant value as its parameter. For example:
void f( const Invoice& i ) { // constant parameter
int s = i.sum(); // error: 'i' is const
i.giveDiscount( s/2 ); // error: 'i' is const
//...
}
In C++, a constant is declared using the const keyword. Objects declared const have a modified type whose value cannot be changed; their values become read-only. Here is the best of both worlds: efficiency through passing arguments by reference and better encapsulation through const, which exposes only a limited const interface of the object. Indeed, functions or member functions that typically read only the values of their parameters can enforce this usage directly by declaring their parameters const. For these reasons, passing objects by const reference is preferred. However, this means you must implement an appropriate const interface for your classes from the start; in other words, your class designs should be "const correct". More on that later. First, now that you can see an immediate practical benefit to declaring constant values, we should look at const in more depth.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- Linux Systems Administrator
- New Products
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Designing Electronics with Linux
- Dynamic DNS—an Object Lesson in Problem Solving
- Using Salt Stack and Vagrant for Drupal Development
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Favorite (and easily brute-forced) pw's
44 min 2 sec ago - Have you tried Boxen? It's a
6 hours 35 min ago - seo services in india
11 hours 7 min ago - For KDE install kio-mtp
11 hours 8 min ago - Evernote is much more...
13 hours 8 min ago - Reply to comment | Linux Journal
21 hours 53 min ago - Dynamic DNS
22 hours 27 min ago - Reply to comment | Linux Journal
23 hours 26 min ago - Reply to comment | Linux Journal
1 day 16 min ago - Not free anymore
1 day 4 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?



Comments
Thanks
I just wanted to thank you for this great text, too.
I read lots of tutorials and also a big book about C++ and never got behind the const magic (worse: I misunderstood it!).
This finally made my mind clear about const, references and these things.
Very good work!
Great Article
First, thanks for the article. I found it very informitive and well thought through. So much on the iNet today is certainly less than what we would hope for. (Thanks for putting the time into this)
Second, I appologize for my Rambunctious colleagues. (Assuming they are in the profession of Software Engineering and not just college hackers)
Keep up the great work.
Cheers
Re: C++ const Correctness
Great article! :-)
invalid references
> You never can create an invalid reference,
> so f() does not need to worry about invalid pointers.
How about this :
int* x = NULL;
int& rx = *x;
Isn't rx an invalid reference ?
I saw this many times "there are no invalid references" ... it's simply false.
Re: invalid references
Dereferencing a null pointer yields undefined behaviour, so your example is flawed.
Re: invalid references
Dereferencing a null pointer produces undefined behavior. So you are not so much 'creating an invalid reference' as you are invoking undefined behavior (by dereferencing a null pointer).
Your compiler may accept this program, however at run time it should crash when you dereference 'x'. If it does not, that does not mean you are creating an invalid reference since any behavior after this point is undefined.
Re: invalid references
Correct!
Especially bastardish in multi threaded applications and dynamically created objects.
Sometimes it is really easier to just use pointers because you can at least check if they are != 0...
Re: invalid references
No, since using pointers in function interfaces is ambiguous at best. For example,
void foo( int* x );
Here, there is no indication whether nulls are allowed or not. If they are, who is at fault: the calling function or the called function? Using references removes all ambiguity:
void foo( int& x );
The fewer pointers you have in your interfaces, the less time you will spend running around chasing nulls.
Effective C++
Was just reading Scott Meyer's 2nd ed of Effective C++... It's great to get another walk through on this topic. Articles like this are the best... I don't have to know huge amounts about c++ to learn this one part. Please do more articles like this!!!
Thanks!
Re: C++ const Correctness
That's all fine and well.
But doesn't all this messing around with const really show that C++ is not the greatest language for object-oriented development.Most people are just content to accept this less than adequate language as if there is nothing better.No one to blame but yourselves. Try reading about a number of other.programming language architectures and then, if you are bright enough, you'll realize there are some compelling alternatives available.
By the way, C++ is not a pure object-oriented language.It is a hybrid. True object-oriented languages typically consider all types as objects, not just those types that are instances of classes
And contrary to the author's point of view, the most fundamental unit of development in C++ is not the class. Classes are extensions of structures in C++.
Use a better langauge and these 'const' issues are just noise.
Go figure..
Re: C++ const Correctness
I'm assuming the author is a Java programmer. It always seems like those people that use other languages like java forget where they came from. If you go read those other programming langauges most the time you will find "...uses a C++ like syntax".
Anyways without going into a fifty page rant, it pretty much boils down to this. If you don't like C++ don't use it... unless of course you need to write a driver for your new unsupported sound card.. opps can't do that in java.. sorry.. but you should be ok writting that next high speed 3d shoot em up.. opps.. can't realy do that in java either..
Re: C++ const Correctness
Don't assume. It makes you look less intelligent, especially when you can't spell "oops" correctly. Most people that complain about the speed of Java are simply bad programmers. C and C++ have the brute force to let bad programmers write fast code, where Java will penalize the programmer who really doesn't know how to program, which is generally the case. Just because Java is easy to program, it doesn't mean that it easy to program correctly.
And actually, you can write high speed 3d graphics in Java, just don't try it with Swing or AWT. Unsubstantiated conceits like this betray the meaning of what you were trying to say with your reply..
Despite the author's commments and even Bjarne Stroustrup's various digs at his own language, C++ can be an elegant and effective language, both in it's C and object-oriented forms. Cornering yourself into a single language because of some herd mentality that it is just "better" is just plain silly. Each has it's strengths and weaknesses that should be evaluated for a project, and hopefully the "best" for that project is used.
Re: C++ const Correctness
FORTRAN RULES FOREVER!
Re: C++ const Correctness
True object-oriented languages typically consider all types as objects, not just those types that are instances of classes
Even true object-oriented languages like Java do not treat all types as objects. They have basic data types like int and char. Every language eventually has to be compiled down to machine language and machine language does not recognize objects. Each programming language has its strengths and weaknesses.
True Object Oriented Languages
That's true, although the standard Java library does re-implement primitives as classes.
Of course, what takes C++ out of the "pure object-oriented language" category is the fact that it doesn't force all functions to be members of classes, and ultimately uses a non-member function as the program entry point. It has nothing to do with whether the language has primitives (the only languages I've used that *kind of* don't are high-level languages that use scalars -- which are basically primitives.) The original poster simply didn't know what he/she was talking about.
Oh, and by the way, 'const' is a reserved keyword in Java, they just don't use it for anything (yet) to my knowledge. I do know there has been talk to add similar functionality to that language.
Anyways, this guide was exactly what I was looking for when I typed '"c++" +const' into google. Great article!
Re: C++ const Correctness
Incorrect. Though C++ is a hybrid, and this is a strength because it allows the user to choose the paradigm to employ, an object can be of any type. Objects that are of a class-type are not special in this way. You might only consider arrays not to be first-class objects (but they are objects, just apply sizeof to one), and you can use features like std::vector or boost::array if find that a hindrance.
Re: C++ const Correctness
> And contrary to the author's point of view, the most fundamental unit of development in C++ is not the class. Classes are extensions of structures in C++.
Incorrect. In C++, structures are classes, ones with all members defaulted to having public accessability. This is the only difference between a class and a struct.
Re: C++ const Correctness
Bases and members both.
Re: C++ const Correctness
Thats interesting, if those who could program well while having to deal with all these const are not "bright", then what does it make those who cannot handle it?
Re: C++ const Correctness
An important issue has been left out: overloading of methods on const. This is used extensively in the STL:
class vector {
//...
iterator begin();
const_iterator begin() const;
//...
};
It is very probable that a container class such as vector is implemented with copy-on-write sharing, and that the non-const version of begin() would already cause such a copy (a detach) to happen. I have thus started to maximise the const usage in my applications. I will go to moderate pains to be able to declare a temporary variable const, e.g.:
const std::vector v = someBool ? someFunc() : someOtherFunc() ;
instead of
std::vector v;
if ( someBool )
v = someFunc();
else
v = someOtherFunc();
The pain becomes moderate if you start to nest ternary operators, which can be done surprisingly readable, but there comes always a point where you want to refactor the mess into a function of its own.
Using const temps also forces you to use proper scoping and init-on-declaration, which is a worthwhile goal in itself (it saves ctor and assignment operator calls).