How should I learn C++? I hear that the language gives enough rope to shoot myself in the head, so should I treat every C++ line I write as a potential minefiled?
-
5Get Scott Meyers "Effective C++" books, they're master classes in NOT shooting yourself in the head/foot. Many sections start with "You can do 'xx' with C++, but really, don't do that because (lists many issues). If you REALLY need to do 'xx' then this is how to do it safely" – Binary Worrier Dec 23 '09 at 11:31
-
3"Just double check your damn pointers, Okay?" http://xkcd.com/371/ – Pete Kirkham Dec 23 '09 at 11:34
-
22It also gives you enough bullets to hang yourself. – Firas Assaad Dec 23 '09 at 11:43
-
1Do you already know any other programming languages? Where are you coming from? – jalf Dec 23 '09 at 12:13
-
1I believe the correct quote would be that C++ gives you enough rope to blow off your whole leg ;-) – Dan Dec 23 '09 at 14:35
11 Answers
How should I learn C++?
Refer to:
- Books to refer for learning OOP through C++
- https://stackoverflow.com/questions/631793/good-book-to-learn-c-from
- The Definitive C++ Book Guide and List
- https://stackoverflow.com/questions/1122921/suggested-c-books
- https://stackoverflow.com/questions/1686906/what-is-a-very-practical-c-book
- https://stackoverflow.com/questions/681551/a-c-book-that-covers-non-syntax-related-problems
I hear that the language gives enough rope to shoout myself in the head, so should I treat every C++ line I write as a potential minefiled?
A C++ statement can do either what you want it to do, or something else. This depends on your understanding of what that C++ statement means. But this is not specific to this language.
By learning the language, and using techniques for building correct software (like Object Oriented design, especially Design by Contract, and testing techniques), you will be able to guarantee that your program behaves as you intended it to.

- 1
- 1

- 22,454
- 9
- 63
- 116
I love your metaphor! What Stroustrup actually said was:
http://en.wikiquote.org/wiki/Bjarne_Stroustrup
C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.
This was many years ago. I started learning C++ in ca. 1991 and it really was a minefield. There were no common libraries, no debuggers and the AT&T approach used a C code generator. There are now many good IDEs which support C++.
Personally I moved to Java because I find it a cleaner language but C++ is fine as long as you don't try to be tricky. Avoid native C constructs where there are existing class libraries (Stroustrup initially did not provide a String class as he though it a useful "rite of passage" to have to write one!) Now you can use a proven one.
I'm assuming you have no choice in the language. How you go about it depends on where you are coming from. C++ is not the easiest of the object-oriented languages to start on and Stroustrup's book is not necessarily the best intro.
UPDATE the OP is worried about blowing themselves up when learning the language. Generally it's a good idea to start with a subset of what one will do later. I assumed the OP is worried about:
- Things which you have to know and use whatever level you program at (such as destructors)
- Things which add additional complexity to the learning process and can be shelved until later (such as multiple inheritance)
what follows are some places where I blew myself up... They are not subjective, they happened!
There are some up-front gotchas that don't exist in Java or C#.
- destructors. You have to manage your own memory. Failing to write destructors will blow your fingers and toes off.
- equality. You will have to write an equals method (in simple Java you may get away without it)
- copy constructor. Ditto.
a = b
will invoke this. Bites you in the bottom.
And I'd suggest avoiding multiple inheritance unless you really need it. Then avoid it anyway.
And avoid operator overloading. It looks cute to write:
vector1 = vector2 + vector3;
but
vector1 = vector2.plus(vector3);
is just as clear, only a few more characters, and you can search for it.

- 37,407
- 44
- 153
- 217
-
1+1, although i disagree on MI - for mixins its just way too useful, you only have to watch out for some basic gotchas. – Georg Fritzsche Dec 23 '09 at 12:04
-
5And I disagree on the operator thing. Of course you should avoid overloading operators when the semantics are not obvious. You could make an argument that `+` for string concatenation is a bad idea. But if you can't think of a better name for the operation than `plus()` **anyway**, it's a strong hint that you should have just used the `+` operator. – jalf Dec 23 '09 at 12:11
-
1Actually, +0 for the subjectiveness, MI-comment and operator overloading combined. – Georg Fritzsche Dec 23 '09 at 12:11
-
It's a subjective question (although a useful one). If the OP is like me then my answer would be useful. I expect s/he will make their own judgment from the several answers. – peter.murray.rust Dec 23 '09 at 12:22
-
1Using RAII (smart-pointers, stl-containers) already solves a lot of the destructor/copy-constructor/assignment hassle. About equality: the compiler tells you when he needs it. – stefaanv Dec 23 '09 at 13:15
-
If the OP is like you, then he already knows your answer, and there's no point in writing it up here. ;) If the OP is incompetent, then he might like every answer that tells him to do the wrong thing. "What the OP is like" probably isn't a very good metric for judging the quality of an answer ;) – jalf Dec 23 '09 at 14:24
-
@jalf: **+** for string concatenation is a terrible choice simply because it goes contrary to the principle that an operator overload does not break the algebraic properties of the original operation. and string concatenation is not commutative. – just somebody Dec 23 '09 at 18:35
-
`a = b` invokes the assignment operator, normally. The copy constructor is only used to initialize an object (it's a constructor). – David Thornley Dec 23 '09 at 22:07
-
@just somebody: I agree with you in principle, but matrix multiplication is not commutative either. There are probably branches of mathematics dealing with non-commutative addition as well. So it's not quite that simple. But yes, I agree with you on string concatenation. It's kind of acceptable because it's so common. But it's not really a good example of operator overloading – jalf Dec 24 '09 at 00:06
Well, it's not a minefield.
Really, the most problems are related to anything related to pointers, so you'll have to understand them (which it's not easy at first) and be careful when using them.
I think it's more a question of experience, having all the basics clear and trying to get a clear design since the beggining.
More than a minefield, I think it's like going to the most dangeours neighbourhood in your town. Yes, it's dangerous, but only for the ones without the attitude. :-D

- 6,283
- 6
- 33
- 46
I would say that that C++ is a challenging environment, if not a minefield. The fundamental issue is that problem symptoms and problem causes are not always easy to tie up. As Khelben has said one major reason for that is that we have pointers to deal with and hence we can do quite a lot of damage when pointers are not pointing where we think they are.
So you need to pay special attention when dealing with arrays and pointers, out-by-one errors can result in memory corruption and these then result in interesting problem manifestations.

- 54,992
- 14
- 74
- 117
Every formal language is a minefield. There're less mines in managed environments. For instance, in C# if you overblow an array you won't cause someone else's remote function to do strange things. You won't have code run differently in tests and prod because someone forgot to initialize a variable in constructor.
However, these are the easy ones. You learn to avoid them, and then you stay with the real mines, which are there in every language.
More specifically, these are some of the most important points when moving to C++:
- always initialize variables. even theoretical possibility of having your program logic depend on what was in the memory beforehand is a nightmare.
- dependencies: avoid data members of other compound types (classes) without pimpl idiom. This will make your users exposed to the inner workings of the types you use, and increase compilation time dramatically. Dependencies are your enemy.
- in C++, you can optimize for performance in ridiculously huge number of ways. don't. Unless you are in the innermost loop of a heavy math software, and even then don't.
- avoid DLLs on windows. They don't work with singletons, causing problems to popular libraries.
- use boost, shared pointers whenever you can. avoid reinventing the wheel and regular pointers.
- use std::string, smart containers instead of arrays. These are dangerous. It will be faster than managed containers anyway.
- use RAII. This one is priceless.
- prefer data members to inheritance, or you will expose the base type definition to your type's users.
- learn to avoid nested includes with forward declarations.

- 18,794
- 5
- 57
- 67
-
I wondered what 'pimpl' meant. Seems to be "pointer to implementation" – Adriano Varoli Piazza Dec 23 '09 at 11:59
-
@Adriano: It's from the prefixed pImpl(ementation) notation. I still prefix my pointers with 'p'. – stefaanv Dec 23 '09 at 13:20
-
Pimpl is not because of the prefix, but because it then makes an easy to remember pattern name. Look here: http://en.wikipedia.org/wiki/Opaque_pointer#C.2B.2B – Pavel Radzivilovsky Dec 23 '09 at 13:45
-
1That's how it was told to me and still believe it because it is the most likely way to come up with a stupid name for the idiom ;). Your link doesn't really contradict what I'm saying, but anyway, it's just another stupid name. – stefaanv Dec 23 '09 at 14:18
-
The corollary to initializing variables is to declare them at the point of use, when you have something useful to initialize them to. Nested includes are often necessary, so learn not only forward declarations but include guards. – David Thornley Dec 23 '09 at 22:08
How should I learn C++?
depends. where are you coming from? anyway, I'd suggest:
- use an up-to-date compiler such as gcc-4.4 or 4.5
- C++0x is worth it for the type inference alone (local variables don't need explicit type designations)
- write small, standalone, short-lived utilities (try porting such tools written in other languages)
- STL has complex parts, but the basic things are easy, don't shy away from it. FMPOV it embodies the spirit of C++
- use state-of-the-art C++ libraries: stuff like Boost.Foreach, Boost.Tuple, Boost.Regex or Boost.Optional turn C++ into serious competition in the scripting department
when you're comfortable:
- learn to generalize your code with templates
- learn to use RAII
then:
- add C libraries to the mix. this might be the first time you'll need to tinker with pointers and casts!
- add OOP if you feel like it
should I treat every C++ line I write as a potential minefiled?
be cautious, but don't worry too much. it's true that you can't know what a + b
means without knowing the whole program containing such an expression because of operator overloads and argument-dependent lookup, and I've seen many people whine about it. a killing counter-argument is that you cannot really know what a->plus(b)
does in Java or a scripting language in the face of inheritance: all methods are virtual, yoyo effect in extremis! (this does kill me in large codebases with rampant inheritance written in languages w/o ADL or operator overloading!)
anecdotes from my experience learning basics of C and C++:
- C: unless you do something really, really, really stupid, the program will compile just fine, and SIGSEGV or SIGBUS as soon as you run it
- C++: unless you do something really, really, really "clever", the program will either fail to compile, or compile and do what you mean (a mantra Perl "inherited" from Interlisp as I've been told).
a ranty post scriptum:
C++ can be used as a much higher-level language than C: whereas you can't do almost anything beyond simple arithmetic without pointers in C, it's possible to write complete programs in C++ without a pointer in sight, save for char **argv
.
there's a whole class of programs that can be implemented in C++ using it as a "scripting" language with unparalleled runtime speed and simple runtime environment (the "dll hell" is nothing compared to the volatility of real scripting languages).
however, the "scripting language" cloak is a leaky abstraction: it's built from native C++ mechanisms such as ADL, operator overloading and templates, and that has its price. get ready for abysmal compile times and unintelligible error messages. OTOH, at least the error messages can be greatly improved with tools like STLfilt, and I think it's well worth it overall.
one thing where C++ really shines in contrast to environments such as Java (perhaps C# too? don't know that one that well) is destructors (vs finalizers and GC). it's one of the pillars of the "scriptiness" of the language. whereas GC adds a whole level of semantic complexity (things don't cease to exist as soon as they're inaccessible from the program) and syntactic verbiage and duplication (finally
), destructors are the workhorse of natural semantics and obviate code duplication that's unavoidable with finally
.
BTW, "enough rope to shoot myself in the head" almost killed me. I think I'll borrow it. ;)

- 18,602
- 6
- 51
- 60
-
A good answer, but overly optimistic on C++. I can get things to compile in C++ a whole lot easier than I can get them to do what I mean. – David Thornley Dec 23 '09 at 22:12
C++ has some pitfalls certainly, but writting safe code is certainly possible.
Some things to think about. There are far from the only things for writting safe C++ code but they seem like a good start.
- Use std::string and std::vector to store strings and collections rather than C style strings and native arrays. They are much easier to get right.
- When you allocate an object using new always think about who owns the pointer to this memory and is responsible for deleting it. If you can't think of a single owner for the data that manages it's lifetime, then either rethink your design or think about using a "smart pointer" to manage the lifetime.
- Prefer indexing into arrays rather than using pointer arithmetic where possible. Whenever you index into an array every time ask your self "How do I know that this index can only index a valid index in the array".
- If a class has a pointer to some data then write methods to act on that data. Don't write methods that return that pointer or at some point you'll end up using the pointer after the data has been deleted. (Not always possible but something to aim for)
If you write simple code that uses strings and vectors and as much as possible encapsule pointers as members of classes that both manage the lifetime of the data and provide the methods that act on that data then that's a good strarting point.
As others have said, read effective c++ and other books.

- 29,554
- 19
- 87
- 130
In C++, foot shoots YOU.
The question is do you need it for anything? If you want to make game code, 3d tools, or something similar you pretty much have to have it. If not, you don't. The errors people are afraid of are seldom big killers but there are plenty of other things that will come up if you make a large enough project.

- 777
- 3
- 7
You may find this spoof interview with Bjarne Stroustrup to be enlightening:

- 52,939
- 59
- 191
- 278
-
-
@jalf: OK, fair point. I think that one good point made by the article is that programmers shouldn't feel duty bound to use every feature of a language every time they program using it. – Richard Ev Dec 23 '09 at 14:46
-
Stroustrup wasn't particularly amused by the spoof interview, and it certainly isn't enlightening. – David Thornley Dec 23 '09 at 22:10
The syntax of C++ is easy, just like Java or C# with pointers. So learning C++ is fast.
The hard thing is that when it comes to a project, C++ is harder to use and more error prone compared to Java or C#. It is just too flexible and the programmer is responsible for too many things.
In a 100 lines of code, you don't need to worry about memory and null pointers at all as you can find them quickly. But when it comes to 10000 lines of code, memory management could be hard. The exception mechanism in C++ is also weak. Thirdly, you need to worry the null pointer problem in C++ in a big project.

- 16,980
- 13
- 75
- 117
I look at the dilemma from a different perspective. The more discipline you have in development the faster you can develop quality robust code. Assembly requires more discipline than C. C requires more discipline than C++.
Don't worry about hanging yourself, blowing your foot or leg off. Just work on improving your quality develop process. For example, a code review will help regardless of the language. Unit testing and test frameworks will also save some bloodshed. Everything boils down to project deadlines and money.

- 56,849
- 17
- 98
- 154