tags:

views:

4169

answers:

33

Most opinions on Stack Overflow seem to voice a similar opinion: C++ is "harder" to use and it is a "bad" choice for a beginner. Speaking as someone who has been learning C++ as a first language, on my own time as a hobby, for a few months, it doesn't seem all that hard. Admittedly, the first time I took a look at pointers and their relationship to raw arrays, the reasoning behind them seemed flimsy. That was before I created my first stack.

In fact, when I look at C# or Java code, it seems restrictive - why should I have to write a class to print "hello world?"

I guess my question is: what exactly (actual features; don't give me broad generalizations, please) makes C++ harder/bad for a beginner, like me? Alternatively, what makes Java/C#/Python etc. easier?

(This question might seem naive, because I might not be familiar with the lower level facilities. I have not messed around with bits/bit shifting or anything like that. I also have not done any GUI/game programming.)


These are some reasons accumulated by the following posts:

  • Relationship between arrays and pointers
    • Pointer arithmetic
    • off by one errors (not C++ exclusive), and no bounds checking
  • Templates
  • Manual memory management
  • code modules (not C++ exclusive)
  • Preprocessor
  • string support not built in

Some solutions to these problems include:

  • Smart pointers for memory management
  • RAII for memory management
  • iterators for off by one errors
  • std::string && std::vector to mitigate the dmg that char* and arr[] cause


Another common complaint seems to be people's insistence on C++ being "C with Classes." I think good programming makes this a moot point, since a good C++ program will avoid procedural programming wherever possible. A good programmer can also avoid the use of the preprocessor where possible (with the exception of module support, where it is a best practice).

Several responses say that C++ is "too large," referring to either built-in facilities or the STL. I think this has less merit because beginners can focus on a small portion of the language to begin with.

Jalf raises an interesting point that C++ is not necessarily hard because of its broad feature range, but because it requires you (there is no option to ignore it) juggle that WHILE learning to actually program. That interpretation is one of the most plausible I've seen yet.

Others so far have raised issue with the unspoken assumption: C++ is harder to learn for beginners. I think it has been pretty hard to learn, but I obviously have nothing else to compare it to. You won't know if your first car handles well until you've been in another. I think it is an understood truth that learning C++ is like learning a manual transmission as your first car. You understand it better later on, but you still end up riding that clutch too much. (It takes courage to ride a metaphor that long, but I did it.)

Common consensus seems to be that once you master C++, mastering any other language is extremely easy (with perhaps the exception of a functional language like F# or Haskell). This seems to be one of the more useful reasons to learn C++ the first time.


Jalf raised some interesting questions about my own knowledge of the language, with this question:

Just for kicks, let's have a few code examples:

int arr[10] = {};
int* p0 = arr + 1; // 1
int* p1 = arr + 10; // 2
int* p2 = arr + 11; // 3
int v0 = arr[11]; // 4

int arr2[5];
int* p3 = arr2 + 2;
int diff = p0 - p3; // 5
float* fp = reinterpret_cast<float*>(p0); // 6

int i = 42;
int j = i++ + ++i; // 7

Which of these lines are legal, and what is the result of them? (Hint: Only three are valid C++, and of those, one of them returns an unspecified value)

My guesses were 1, 5, and 7 were legal. It turns out 1 and 2 are moral and 6 is legal. That was a little bit of a wakeup call as to how intricate my knowledge of pointers are in C++.

Update:

Since this question began as defending my choice of C++ as a first language (and, as of right now, my only language), I figured I should update the people who responded on my progress.

My biggest problem with programming, as of right now, is simple: I don't know how to do anything. Sure, I can write a class that is useful to someone else, but I cannot write anything that would be useful to me in any way. I am not sure, however, if that has anything to do with C++ as the first language - I'm wondering if I'm just not built to be a programmer. It's enjoyable (and extremely frustrating at times), but I'm not sure if I could see myself doing this full time in the future.

One thing I dislike about it is that there are too many solutions to the same problem. This is conducive to several different types of programmers, but I don't feel like I fit the mold of any of them. I think this IS partly C++'s fault, but I could not tell you how I would feel about another language like Python until I've tried it.

I play tennis in my free time, and then solve sudoku if that or socializing are not options. Both of them have multiple ways to solve problems - if my opponent rushes the net, should I lob or try and hit a cross-court shot that he cannot volley? Both methods have easily visible upsides and downsides (the former being, what if it is not high enough or it goes out? The latter being, what if he tags it for a winner on the cross-court?)

The same is not true in programming. One method that looks absolutely fine to me might be hackish, slow, overly complex, or overly simplistic to another programmer. This, coupled with my lack of time/motivation to continue programming, has kept me from doing more than writing a small amount of code each week.

Can anyone think of a way to motivate me past this stage, or do they think I should just give this hobby up?

+8  A: 

There can be plenty of reasons such as complexity and a lot of corner cases but I believe the high order bit is manual memory management. In C# and Java, there's not much to deal with memory management issues (err... at least nowhere near C++) but I haven't seen a reasonable C/C++ book that doesn't cover pointers before it's, say, Chapter 4.

Mehrdad Afshari
True, but you can use STL to avoid most of this stuff. The again, when you use STL, you may as well start with a scripting language and avoid templates at the beginning.
Arkadiy
Arkadiy: Learning a language does not mean *only being able to code in it*. It also involves reading others' code and integrating with it. Personally, I see pointers as fundamental concepts of C/C++ without which I can't say someone knows C++.
Mehrdad Afshari
STL hardly solves all your memory management problems. You still have to keep track of your own allocations (or at least know how to write a proper RAII class where copy constructor or assignment operator won't accidentally leak or double-free something.
jalf
@Mehrdad, I disagree. C is not better than C++ in regards to memory management. However, C is a very simple language, while C++ is very complex.
Igor Krivokon
@Igor: When did I compare C to C++ that you're disagreeing with. I just compared C/C++ to others.
Mehrdad Afshari
@Mehrdad: Comparing "C/C++" to others is like comparing "Javascript/Java" to others. C and C++ are different languages. C is a simple language (in my opinion). C++ is a complex language. You pointed to a feature that is present in both languages, so it can't explain why C++ is a complex language.
Igor Krivokon
@Igor: C++ is much more complex than C but they are similar in the point I am making (both being **non-garbage collected languages**). I didn't say C and C++ are identical or anything stupid like that. In this sense C, C++ are on one side and C#,Java,Python,Javascript are all on the other side.
Mehrdad Afshari
Smart pointers solve most memory management problems, and RAII solves most problems with resource allocation. In this respect, C++ is easier than Java.
David Thornley
@David. to do this in C++ as a beginner means at the very least learning how to implement RAII... in java or c# you simply don't. That you percieve RAII as easy is all well and good but _any_ additional complexity or knowledge needed for a beginner to get a functional non crashing program is an increase in difficulty to a large majority of the population.
ShuggyCoUk
So, you're saying that novices don't need to manage resources in Java or C#? I rather doubt that. Similarly, in C++ there's no need for a novice to explicitly manage memory, when the novice can use shared_ptr<> rather than raw pointers.
David Thornley
But the difference is that they need to know *when* to use them. They need to know they exist. Anything they have to learn to be fucntional in a language is impedance to learning it. This doesn't make it *bad* it just makes it harder to learn. If you are learning java/c# then you can 1) only need worry about freeing up things if you actually use them (in c++ you need to worry about it if you allocate) and 2) can even not bother and rely on finalization.
ShuggyCoUk
The latter is obviously an appalling habit, and this may overall be a negative for the resulting learning experience, but crucially it gets them up and _running_ gets them going. The barrier to getting their first stab at a program gets less and less. Stop thinking I'm saying these things aren't *important*it's just that, to a beginner if you can simply not even know they _exist_ you can get going (for good or ill) faster
ShuggyCoUk
Using RAII in C++ isn't that hard - mostly it involves choosing *not* to manage pointers manually - ie, don't call new and delete and you're using RAII! Easy! (If you must... Then smart pointers will save you)
Arafangion
+2  A: 

Here's a stream-of-consciousness list:

The compile/run cycle takes longer than interpreted languages like Python, Perl or Ruby. Static types are not usually known to non-programmers. The Standard Template Library and other template-based language facilities use templates, which is another barrier with a new syntax along with unintuitive compiler errors. There are some tricks to inheritance, including default constructors, multiple inheritance and virtual destructors. The concept and syntax of pointers is a hard thing for new people to learn. Memory management is important and non-trivial to learn, and it's important to do if you do serious programming with other people who write C++. Error messages can be opaque and difficult to understand, both from the compiler and at run-time.

The bottom line is that C++ has a lot of domain-specific knowledge that you just need to have in order to understand the programs that people write, and that's a barrier to learning. Languages like Python and Ruby are much simpler, which means that you can more quickly get to the point where you're learning more general programming concepts and less specific knowledge about a language.

James Thompson
This answer seems cryptic. Please remember I am one of those beginners!
Hooked
I don't think this is *the* point, but it's true. First, an interpreted language doesn't need to be compiled at all. You can run Python directly without compiling it, which means that you can instantly fix bugs, rerun your program, debug it, fix a few more bugs and rerun. Compiled languages introduce the extra step of "compile your code" between fixing bugs and testing the result. Additionally, C++ takes ages to compile. Almost all other compiled languages would be better in this respect, even if they can't compete with interpreted languages where no compilation is needed.
jalf
I tried to add more detail. Hopefully it helped!
James Thompson
Yes, thanks very much James. I ran into the problem with the default constructors myself (although the explanation behind C++ tricking me was sound: it is for backwards compatibility with C), and I'm still learning when to use virtual functions. I think the problem with these things is more design of the code then the code itself. I do agree the template syntax is confusing; writing a T max(T x, T y) function was scary. But then again, I find the little F# code I have read impossible to decipher, and a lot of people herald it as the future.
Hooked
Functional programming is tough to get your head round. It requires some time forcing yourself to use it properly (rather than 'chickening out' and using a loop :)). I learnt FP before imperative but then didn't use it for 10 years. Going back to f# was tricky!
ShuggyCoUk
+26  A: 

Restrictive is easier. Both C and C++ lets you shoot yourself in the head (and those around you) at every turn.

That said, I think both C and C++ are fine languages for a beginner, but you really should have someone around to guide you and review your work if it is at all critical. A mentor, if you will.

jeffamaphone
Luckily, I do have that. A game programmer on a forum I frequent is a professional programmer. He is the one who assigns me things I ask about on here (look at my profile for previous questions). My impression is that he is extremely good at his job. I believe he came in third in a game dev competition, and that's how he landed a job at a dev.
Hooked
he might be good, and if he's able to teach you C++ well, that's certainly a good sign, but in itself, coming third in a game dev competition doesn't mean much. Most game dev competitions focus on the gameplay, not the technology behind. A few years ago, gamedev.net hosted one where the winning game was made in Gamemaker. It was a better game, but it doesn't mean that the programming that went into it was anything impressive.
jalf
Sure, I understand that. Although I think the technology behind his game was his own - he wrote his own engine and designed his own specs. My personal take is that he's a great programmer. That might be biased because he is helping me learn. I do know that the winner of that competition is (well, afaik) still not a pro game dev (I think he did use a prepackaged engine like Spring or something).
Hooked
I am currently studying game design. Be wary what they teach you. Back in The Day game programmers just needed to get the game done and shipped and that was that. Whatever worked and got the job done. So they tend to teach non-standard or bad ways of doing things. Just remember you should always try to do things the standard, cross-anything way. Don't use a raw array because it might be "faster", use a std::vector. Good, standard, elegant design first, optimize last.
GMan
No answer that refers to some language called "C/C++" deserves to be upvoted like this.
anon
@Neil Butterworth: Wah.
jeffamaphone
He's right. It is true that C/C++ (as in C or C++) let you shoot yourself in the head. It is not true that "C/C++ is a fine language for a beginner") You could argue that *they* are fine *languages*, but they're not one language, and they don't really have much in common.
jalf
Well, the easy part of C++ to learn is the subset that is C (minus some nasty features that no one wants). From my point of view, C++ is a superset of C that consists of the following: C, the C standard library, the STL, and C++ OOP features. Is this wrong?
Hooked
well C++ is statically typed and C isn't so the superset argument there is somewhat disingenuous...If you are referring to C++ refer to it directly, if you are reffering to C likewise. If you are writing C but doing it in a way that a C++ compiler will accept it then that's about the only time the phrase is really meaningfull (and it's bloody hard for anything non trivial)
ShuggyCoUk
@jalf Good point. I'll fix that.
jeffamaphone
+4  A: 

this mainly because you had to consider many other factors other than just the program logic itself when you program in C++. Things like pointers, memory allocations and cleanups are usually nothing to do with the program logic itself but low level machine details.

On the other hand, when you program in Java, C# or Python these details are hidden away from the programmer's view. Therefore, a beginner can just focus on learning the logic behind programming rather than getting scared away by all these complex factors around him/her.

oykuo
+70  A: 

Speaking as someone who has been learning C++ as a first language, on my own time as a hobby, for a few months, it doesn't seem all that hard

Well, you could have learned another language in a week. ;)

But more importantly, how many subtle bugs do you think your stack contains? It's not hard to write something that a C++ compiler will accept. With a bit of effort, you can even make the resulting program seemingly behave as you want. But there will almost certainly still be countless subtle but critical bugs. Of course I can't pinpoint them without seeing some of your code, but I'm willing to bet they're there.

You're right, C# and Java are restrictive. Which is a blessing and a curse. In some ways it is a pain (like you say, having to create a class for a simple "hello world" is silly, although it makes less difference for larger programs - other languages don't require the class though), but the advantage to it is that in being more restrictive, the compiler is able to catch a huge number of errors that in C++ would have gone undetected until you ran the program. Or perhaps until someone else ran the program on a different computer, on the first monday in May. The problem with C++ is that bugs become hugely unpredictable.

C++ is a huge language, and learning all the subtleties of it takes forever, but that's not the reason it's a bad beginners language (if that was all, beginners could just focus on a small subset of the language initially). The real problem is that it is extremely difficult to get right.

And simply that when you're learning programming, the important part is really language-agnostic. Learning to express yourself in code, breaking any problem down into something that can be expressed in terms of a programming language, that's the important skill. But C++ forces you to learn that while also juggling a very complex language, where you also have to figure out pointers, manual memory management, deal with out-of-bounds array accesses, cryptic template compile errors, memory leaks, more memory leaks and countless instances of undefined behavior. (cases where the compiler accepts the code, but the language standard does not specify any behavior, which means that anything might happen, even if the code seems to work. C++ features a huge number of these cases, whereas most languages try to catch or prevent all such errors at compile-time)

It would typically be far more efficient to focus on one at a time. Start out learning programming in a language that doesn't place too many hurdles in front of you. And then, when you've got a grip on programming in general, you can focus on the intricacies of C++.

(I know that I haven't mentioned many specific features as you requested. The problem is that most of the individual features of C++ are relatively simple (template specializations and pointers tend to trip people up, but they're manageable, at least. Template metaprogramming would probably drive you insane, but that's normal ;)). The problem is all the plumbing in the rest of the language. The many unpredictable errors that only sometimes surface, and only when you run the program on some computers, on a bad day, or the problems you might run into trying to get the constructor, copy constructor, assignment operator and destructor on your class to all work together to ensure no resources are leaked and that the class is always in a valid state.

The problem with C++ is all the things that seem to work.

Edit

Just for kicks, let's have a few code examples:

int arr[10] = {};
int* p0 = arr + 1; // 1
int* p1 = arr + 10; // 2
int* p2 = arr + 11; // 3
int v0 = arr[11]; // 4

int arr2[5];
int* p3 = arr2 + 2;
int diff = p0 - p3; // 5
float* fp = reinterpret_cast<float*>(p0); // 6

int i = 42;
int j = i++ + ++i; // 7

Which of these lines are legal, and what is the result of them? (Hint: Only three are valid C++, and of those, one of them returns an unspecified value)

jalf
Couldn't the bugs be prevented by simply designing good algorithms? If something goes awry on the first monday in May, doesn't that just mean you wrote bad code, not that the language is (by definition, necessarily) too free? As for my node based stack class, I would like to think I designed it bug free. Every aspect of my code has a reason, and the person who is helping me to learn stresses commenting code. I think the errors you are referring to have just as much to do with the programmer as they do the language. Maybe I just learned the right way the first time.
Hooked
You're right, if something goes wrong on the first monday of may, you obviously have a bug. The point is that most languages would have caught this bug at compile-time, or at least throw an exception you do something illegal. A typical example is accessing unallocated memory, for example by reading past the end of an array. Most languages wouldn't allow that. They would throw an exception the moment you do it. C++ doesn't. You can happily write over memory until the OS says stop. Which makes the problem unpredictable and hard to trace.
jalf
About your stack, feel free to post it here, or in a separate questions, for review. It could make an interesting learning experience (even if it is bug-free, you'd get a lot of feedback from other C++ programmers, which can be very helpful)
jalf
added a few code examples :)
jalf
Thanks jalf. I did post the code. Here it is: http://stackoverflow.com/questions/1085238/node-based-stack-class-need-peer-review
Hooked
My guesses are 1, 5, and 7. 7 equals (if my operator precedence and general understanding hold up) 83, because i++ is done after you add i to ++i; in the latter case, you add it before adding it to j. Line 5 is stupid because you are trying to A) assign a pointer to an int to an int B) comparing pointers to two different ints. 1 actually seems fine; isn't that the same as (or similar) int* p0 = ??
Hooked
1 and 2 are perfectly valid. 6 is legal, but the value of fp is undefined.5 is bad because you're not allowed to subtract pointers that point to different arrays. 7 is bad because you are not allowed to do more than one modification of a variable (or a modification and a read) in the same statement. There is no rule for which of the two should be evaluated first, or if the input to the second one should be the original i, or the value of i after the first ++ is evaluated. The result is just undefined. You're not allowed to do it. :)
jalf
And those are just the examples I could think of in a few minutes. Just a small sampling of the surprises C++ has in store. :)
jalf
I don't even know how to use C++ style STL casts, I've always done the (unsafe) casts like (int) wasFloat; Otherwise, wouldn't 2 make arr point to arr[11] instead of arr[10]?
Hooked
You should get used to the C++ style casts. They're safer, more noticeable (easier to search for), and easier to understand. The C-style cast does completely different operations depending on which type it's used on.Why would 2 point to arr[11]? arr decays to a pointer to arr[0], so adding 10 gives us arr[10] - or rather, it doesn't, because it gives us the "one past the end pointer", which is allowed to exist (unlike the arr+11 case), but you can't dereference it, so arr[10] isn't allowed.
jalf
just for clarity, you could replace the reinterpret_cast with a C-style cast if you like.float* fp = (float*)p0 would have given the same result. (legal, but the result is undefined)
jalf
Oh, I forgot about the rule that (int* val = arr) == (int* val = $arr[0]).
Hooked
@jalf: 2 is perfectly valid? arr + 9 would be perfectly valid. arr + 10 is asking for trouble ;)
Joseph Garvin
No it's not. That's just a one-past-the-end pointer. That's specifically allowed. Of course, you can't dereference it, but you're allowed to point there. Most of the STL would fall apart if this wasn't allowed, as you wouldn't be able to create an end iterator.
jalf
The discussion in these comments pretty much proves the point. :) C++ has a lot of subtle and occasionally surprising gotchas.
Greg D
WHy would you want to write such C-ish code? If someone *starts* with he will most likely start using STL right away, and skip all the error prone constructs from C.
Milan Babuškov
@Greg: Indeed. :)@Milan: C-ish? But the same problems would occur if I'd used a vector and iterators instead of an array.
jalf
Except that almost nobody does iterator arithmetic.
David Thornley
really? You never need to find the distance between two iterators? Or add to an iterator to skip a number of elements? I'd say those are relatively common operations, enough so that the standard lib bothered to define std::distance for the former, and random-access iterators for the latter.
jalf
Code does compile, with a warning on //7 http://codepad.org/hjCop7C6 with //7 dimmed: http://codepad.org/1wDKVdo0
Liran Orevi
yes, it compiles, but it's still undefined behavior. Just because it compiles doesn't mean it is valid.
jalf
@jalf, thanks, wandered about this.
Liran Orevi
I just sucessfully compiled your example code with cygwins g++ 3.4.4
DaClown
Many excellent points. Totally agree with your central thesis that C++ is large and complex and *you never even know if you're doing it right*. One more thing I'll throw on the pile: the rules for choosing overloads -- particularly when function templates are involved, and/or implicit conversions are involved -- are too complex for words. Otherwise a lovely language ;)
j_random_hacker
+4  A: 

I'd say: 1) split declaration/definition This is fairly minor, but a nuisance, the managing of class and function declarations outside of the implementation. Lots of chances for mistakes, especially early on.

2) manual memory management New vs. delete (and the C malloc/free) whereas many of the alternatives do their own garbage collection and cleanup.

3) c vs. c++ Basically: how to write good c++ vs. a mish-mash of C and C++. The "have to write a class for Hello World" is kind of a lame argument; it's much more about how you organize and structure your (useful) program. Part of what makes C++ somewhat ornery is that it is (a) built on top of C, and (b) doesn't prevent you from smushing the two together and cherrypicking what you want. Useful sometimes, but also makes it difficult to understand

4) evolutions in provided libraries that are native to the environment The libraries and classes provided in .NET and Java offer a lot of reuse potential and make rapid and more robust development possible. C++ has a lot of reusable libraries out there (notably boost) but they are generally add-ons and not part of the native environment. With (say) .NET, I know what all .NET developers are going to have available. With C++, that domain is a lot smaller.

Joe
As for memory management, I think the use of the STL mitigates a lot of this. In any instance where I need to dynamically allocate memory, it seems like the use of std::string or std::vector is a superior choice.
Hooked
I'd say that's true for most malloc/free cases, but there's still the giant task of object instantiation and deletion which you really can't avoid in any moderately complex C++ app.
Joe
but RAII and smart pointers can take care of that.
jalf
Upvoted for #3. Good C++ code nowadays looks about as much like C code as Java does.
David Thornley
+9  A: 

I started with C++ and till now it is my language of choice in college, really :)

For me, I had a really good professor who chose C++ over python, and I would thank him if I could see him again. It took me one week to catch up with Java(the language) and understand why a lot Java programmers in my college till now they don't know that comparing two strings using == is wrong!

C++ is a language, it is not the library, the compiler, nor the IDE. It is a lot much harder to explain to a new comer that these things are not the same. Unlike other languages, they come usually in one package.

Otherwise, C++ is really a fine tool if you give it your effort.

AraK
It is a great point that once you know C++, learning higher level languages is easy. C++ --> Java is simple. Java --> C++ isn't even always possible.
Steve Rowe
Why wouldn't Java -> C++ be possible? Once you know another language, C++ becomes quite a bit easier, just like other languages become easier once you know C++. C++ doesn't have any magic special status there, it's simply the fact that if you know another language, you've already learned programming, so the hard part is over. Now you just have to learn the quirks of a new language.
jalf
you've peaked my interest, why exactly should java programmers not compare strings with ==? is it because of null, if so there is some great discussion over at the daily wtf. I think the contents of the article involved someone saying exactly what you said....
Hippiehunter
I believe == compares the strings' memory address, not the value contained. It's been a few years since I worked in Java, am I right?
NickSentowski
Checked suns site and you're right http://java.sun.com/mailers/techtips/corejava/2006/tt0822.html#2 I guess its a good thing I don't code in java.
Hippiehunter
From what I've seen of a Java guy I talk to, there is an isEqual() function in the Java library (or whatever, he-he).
Hooked
@Hooked: It's `equals()`. and there's nothing to "he-he" about it.
missingfaktor
This is my same story exactly. C++ is super easy if you started with it, and Java is even easier. And now that I'm in classes with other people who started on Java and have to learn C++, I get really confused when they don't understand how pointers work.
Brendan Long
+14  A: 

Memory management

C++ doesn't have garbage collection. It was designed for speed and garbage collection entails a certain amount of background overhead. In C++ you have to manually free memory after you are done. It's not just a mere inconvenience or annoyance, either. Often this just means you have to remember to put a delete at the bottom of your function to match the new at the top. No big deal there.

The problem is when an object's lifetime doesn't line up nicely with any one function call and spans call boundaries. One example of this is when you have a function like gets() which needs to work with a buffer of indeterminate size. You then have several not-so-great solutions, including: (1) take a length parameter like fgets(); (2) allocate memory dynamically and rely on the caller to free it later.

An even more annoying pattern, though, is when an object has indeterminate lifetime, or indeterminate ownership. Say you add an object to several collections so its ownership is shared by all. Whoever owns it last is responsible for cleanup. This situation stinks and generally involves injecting shared_ptr<>s and the like into your code. Or in lots of older pre-boost C++ code, it meant added reference counters to your classes or hacking together a poor man's garbage collector.

Header files

Splitting up declarations and definitions was a necessity 20+ years ago with the incremental compilers and tight resource requirements that existed then. They are completely unnecessary these days and in fact lead to several migraine-strength headaches, vis-à-vis: (1) dynamic Makefile dependency generation; (2) painfully slow build times; (3) unnecessary code duplication.

Templates

Templates are ridiculously complicated. Error messages when they fail are nigh on unreadable. They're so powerful they are actually Turing complete, meaning you can write full programs just using templates and have the programs "run" when you compile your code. Java and C# figured out how to do generics without the C++ template nastiness.

Preprocessor macros

The same thing goes for the preprocessor. Macros can do amazing things but lead to amazingly unreadable code. And it is just oh-so-tempting to throw a little magical macro dust on your code. "Hey, I could just write a little CATCH() macro to make catching exceptions and printing an error message easier..."

Java decided to just ditch the preprocessor entirely. C# was a little less hateful and kept conditional compilation (#ifdef and the like) but threw out macros, which is really all anybody wanted.

John Kugelman
To date, I have only developed for personal use on a windows platform, and the use of const seems to mitigate the need for macros. Templates are hard, but as far as I know it's just compile time polymorphism, so i could just rewrite the same function a few times to support my needs if I really couldn't get my head around the templates. As for your first example: I don't understand what "ownership" means. Would you extrapolate?
Hooked
Ownership as in who's responsible for deleting an object? When does its lifetime end?A local variable is simple, it dies when you return from the function. But what about a value that multiple classes and functions have to access? WHich one of them is responsible for deleting it? How do you ensure that it is not accessed by the other functions after the owner deleted it? How does the owner know when it is safe to delete it?
jalf
It sounds like you're developing good habits. Kudos. I have no doubt you'll grow into a great non-C++ developer some day. ;-)
John Kugelman
Thanks for the explanation jalf and for the vote of confidence John.
Hooked
yeah, I have to agee with John. Sounds like you're doing pretty good so far. :)
jalf
Thank you guys =)
Hooked
I never got why people think "templates are ridiculously complicated." They don't seem THAT complicated. :/ And Generics don't compare to Templates very well, I think.
GMan
I think he explains that pretty well. They easily lead to very difficult error messages, and I'd say that any generics implementation which becomes turing complete is, by definition, "ridiculously complicated". Useful, but still complicated. Of course, if we really want to justify it, we can just say "template metaprogramming". :)
jalf
Most memory management can be done by smart pointers. I don't know why John complains about shared_ptr<>, since it's precisely the right thing to use in many cases. Templates will become easier to use. Avoid macros.
David Thornley
Not a complaint really, just an annoyance when you compare C++ with Java. I certainly do use shared_ptr<>, it's great when you need it.
John Kugelman
Yes, but using smart pointers and RAII gives C++ a unified resource management system, which Java really doesn't have. It's clunkier, but powerful (yes, you can say that about a lot of C++).
David Thornley
C++ a unified resource management system - since there is still no one true smart ptr library I would deny any claim that C++ is unified. That is one of it's great weaknesses. The library was standardized so long after the language that you are doomed to a fragmented user base in this regard. Getting things very close to right first time is really a big deal for the evolution of a language, just look at the pain not having generics from the start causes the collections libraries in 2.0 onwards, so many array returning apis that are messy as hell...
ShuggyCoUk
that incidentally is about the pain of late generics in c#. in jaava it's even worse!
ShuggyCoUk
+2  A: 

Actually, I think it's easier and perhaps a preferred way to learn (when learning just the basics of programming in general). But since it can become a handful awful fast ...just take it slow. None of this "learn to be a master coder in 10 days" crap.

Rev316
+4  A: 
keraba
Good example, +1. Would +1 again for the bumpercar analogy =D
Hooked
(not related to main question)I'd still use: cout << boost::format("%d %f %s") % a % b % c. Much easier to localize and easier to read when your pattern is more complex.
liori
totally awesome for propping c/python and slamming java/c#.
Matt Joiner
-1, crappiest answer here. You clearly have no experience with any other language other than C or C++. I'd even say you don't know much about C or C++ either. (as is obvious from your kiddish example.)
missingfaktor
+9  A: 

The main challenge to learning C++ arises from the fact that the language provides constructs and features at various levels of abstraction (pointers, references, memory-management, value-semantics, user-defined types, object-oriented, generic, functional, meta-programming) that are intended to support not just one, but multiple paradigms of programming. In addition, some of those constructs behave non-intuitively (lack of automatic virtual destructors in classes that are inherited) and inconsistently (such as initialization) - mostly because of the constraint of having to design those features with "C" compatibility in mind - in addition, many constructs don't protect you from "absentminded" behaviors if you operate at the "wrong" level of abstraction.

There are some really good parts to C++, and some really bad parts to C++ - you can write some really simple code in C++ and some really cryptic code - but this is not unique to C++ by any means. You can say the same about Java, ruby, javascript, perl, lisp etc. But C++ is a much larger language than those others - therefore it tends to have many more bad parts, but then it also has many more good parts.

I will admit, modern C++ code does tend to get a little too verbose, and some of the error messages are needlessly cryptic, but the use of auto, concepts and lambdas in C++0x will greatly simplify those issues.

There is also the issue of reputation - in its early days, C++ implementations did not have adequate library support - and some would claim that even in spite of boost.org, the libraries are still inadequate (though improving daily) - without the proper use of adequate libraries, one might be forced to have to deal with memory management and other low-level concepts - the debugging of which may indeed scar someone irreparably - such a reputation is not easily shed - especially if there are technologies out there (ruby, python, java) that are specialized enough (i.e. not designed to manipulate demanding or resource-intensive systems) that they insulate programmers from concerns that may not be relevant to the domain for which they are designing solutions.

And it is worth mentioning that C++ is usually not taught well. Many of the older books start teaching C++ with raw-pointers and character arrays (instead of smart_pointers, strings, vectors), along with all their technicalities and low-level details that are usually unnecessary and irrelevant at the beginner level. There are some really good books out there and if one starts with those, I would imagine they would have a very different experience than someone who uses a book that starts out describing native-pointers and arrays before string and vector.

Faisal Vali
Nice. I never even thought of it in that way: I simply viewed the various C++ features (OOP, imperative, etc.) as a set of tools, and not layers of abstraction. Thanks, +1
Hooked
+2  A: 

It's actually GOOD to learn C (and C++, I suppose...), but there are a lot of gotchas.

Most of them revolve around these three things: Strings (or lack thereof), arrays, and memory allocation/deallocation. These three things probably constitute 99% of the serious bugs in C & C++ code.

I don't want to go into the details, but I'll refer you to a good companion book. If you're going to learn C/C++ for serious development--and regardless of platform--I strongly recommend picking up a copy of Secure Coding in C & C++. I think this is a book every C coder should have. Doubly so, if learning C after having developed on a managed language like Java or C#.

Edit: The one other "gotcha" of C/C++ are the libraries. If you want to do anything serious, chances are the library is custom to the platform. For example, you'd be using the Win32 API (or ATL/MFC/WTL for C++) extensively for just about any kind of Windows development.

hythlodayr
My question is specific to C++. I only use std::string for strings, I prefer to use std::vector for arrays, and memory allocation/deallocation is less of a problem if I pay attention than it might seem.
Hooked
I'd still recommend the companion book. Also, the native "string" in C++ is still char*. As Joel Spolsky points out, it rears its head now and again even if you use the string class.
hythlodayr
I understand that std::string is just a container of char's. It is still way easier to use. I will look at that book, but while I'm just writing my own code (not maintaining legacy code), I don't think I need to know a lot about string manipulation with arrays of chars.
Hooked
+8  A: 

Though C++ might be "harder" than other languages like Java or a scripting language like Python or Perl, "harder" != "bad". Learning C++ kind of forces you to learn how a computer actually works, particularly memory management. For instance, I do not know how you would explain the difference between passing by value and passing by reference without a primer on how memory works. Thus, learning C++ teaches you a lot more than just the language itself. It in a way forces you to learn concepts that will be useful in any language (like why "string" == "string" is wrong). I agree with jeffamaphone when he says that C++ lets you shoot you in the foot, but shooting yourself in the foot (figuratively speaking) I think makes you learn.

PLUS, the biggest thing that shoots you in the foot is pointers, and you don't even need to get into that right off the bat. You can learn things like loops, functions, classes, templates, etc and not touch it. I learned C++ for a year before ever diving into pointers. Then when I learned it, again, I was forced to learn how memory worked without having a garbage collector to hold my hand. Sure, it was "hard", but I learned from it.

I learned C++ first and I think it really got me grounded in good programming. If you're not trying to be a programmer, then learning some other language is fine. But, if you really want to learn how to program, I would always recommend starting with C++ (I would say C as well, but then you miss out on object-oriented programming). Higher level languages will deny you learning experiences that are probably quite critical in the long run.

Ryan
+2  A: 

I don't know what you are working on, but be aware that as a beginner there is a good chance that the problems you are tackling aren't hard or subtle. In that world almost any of the common languages would allow you to write perfectly nice solutions.

C++ supports multiple styles of programming: procedural, OO, generics. In skilled hands I'm sure this is wonderful, but beginners often find it confusing. In contrast, one of the design goals of Python is that for most problem there should be a correct, and fairly obvious 'Pythonic' way of handling it. There may be many better and subtler ways of tackling it, but the obvious way shouldn't lead the user too far astray. In C++ there may be 100 obvious ways of tackling a problem, all of which seem correct, but 87 of which lead to subtle problems.

I'd suggest that you take a look at Scott Meyer's "Effective C++" books. His examples often start with simple class designs that seem perfectly reasonable, and he gradually reveals the subtle problems they cause. You might also try C++ Frequently Questioned Answers. If you can understand his objections to C++ and counter them you are a pretty sophisticated developer.

Charles E. Grant
Would upvote for the Meyer's reference, would downvote for the FQA reference. As a result, I'm not doing either.
David Thornley
+14  A: 

C++ is much harder to learn than python. It is also far more educational.

If you have a willing, competent teacher, I would take the opportunity to learn c++. Once you understand memory management, pointers, strong typing and the like you will be much better equipped for a range of programming.

It's like learning to drive, if you learn using a stick shift then an automatic is easy. If you learn to drive on a automatic, driving a stick shift is a nightmare.

See Joel's article for his viewpoint on Java schools. Many of the same things apply.

The flip side is, for most of the things that you want to program, c++ is not the best choice. For web apps, use .net, python, ruby etc. For windows desktop apps, use delphi or .net etc. But if you know c++, then the others are easy to pick up.

SeanX
I find the assertion "C++ is far mode educational" to be very dubious. It depends what you want to focus on. The big problem with C++ (and in lesser degree C) is that it forces you to focus on details, which often do not matter at all. A high level language enables you to focus on API design, etc... C/C++ are awful languages for prototyping for example, so you can't experiment much at first, when you are a beginner. I agree that you need at some point to know about one low level language, but I don't think Joel's point is that it should be your first.
David Cournapeau
as a C++ programmer, I agree with David. There are plenty of things in C or C++ that are worth learning, but it's mostly a distraction to a beginning programmer. It's something you'd benefit from learning as your second or third language, perhaps, but no point in starting with it.
jalf
+2  A: 

It's the terms "a beginner" vs "a beginner, like me" that's the trick to this question. Since your finding C++ easy to learn, then you obviously get "it" and so it's and ideal language for a "beginners like you".

When people make a sweeping statement that "Java/C# is easier to teach beginners than C++" they are actually thinking about beginners who are "not like you", and would struggle with "C++". They're also going to struggle with Java and C#, but suprisingly, not as much.

I love C++ as much as I love Java and C#. If I was to give one bit of advice when learning a new language is to avoid the trap of "this is how I did this in language A, so how does that translate into language B" but rather, try to come to terms with the underlying philosophy that that language was designed with so that you can use that language the way it was intended.

So when you ask "why do I have to have to have a class just to print hello world?" I would counter ask "why do I have a function main just to print hellow world?". Why is my program not simply:

Print Hello World!

Using this approach, I've never met a language I didn't like (with the possible exception of R-Base 5000).

Some interesting points from some of the other comments on this page:

C++ doesn't have good string support: Well maybe not built in, but there are a ton of good C++ string classes out there.

C# doesn't have pointers: Actually it does, along with all out favourite operators from c/c++ including ->, & and *. Let's face it, there are just some Win API calls that can't be made without resorting to pointers. The difference is that I get to lock these away in special routines I've marked as "unsafe" (a rather poor choice of keyword) limiting any impact they have. I'd bet that 90% of C# programmers have no idea about this, and that's because 99% you don't need to know in C#.

C++ is more efficient and lower level: We'll not really. The early days of 'c' were closer, but these days the compilers generatre so much more assembly than you would ever expect to see. If you want that level of efficiency and control, then learn assembler. At least most C++ languages allow us to write assembly in line so we can take control of that if we want to. But don't get into the "performance is everything" trap. I've seen programmers agonise over things like which is faster, a switch or an if, or worse, sacrafice readability of code for what they think will save a few CPU cycles. Twenty years ago with low end resources I'd probably agree with them. Today, with giga-cpu-cycles going to waste every second, most programs will benefit from a modern productive language that makes the most of the one resource that gets more expensive every day, but whoes capability remains very much the same as it did 20 years ago, the programmer.

From someone who occasionally has to select a language to teach beginners my two biggest concerns are:

i) The squiggly brackets and the sometimes you need a semi-colon and sometimes you don't syntax. This equally applies to Java and C# of course, and is one of the reasons why Pascal and Basic style languages are popular with beginners.

ii) The big one though is that while every language has "subtle" errors, C++ has far more than Java and C#. Inevitably beginners can't get their program to work because of an error they find hard to track down. Besides being frustrating, it burns valuable time that they could be using to learn more. Some relish these, I used to think it was like solving a logic puzzle or a Sherlock Holmes mystery, but others who would otherwise still be reasonable devlopers begin to despise the language, and loose the point that was being taught.

It might be because an int wasn't initialised, or it's because an integer was confused with a pointer or a handle or a pointer to a handle, or a pointer to a pointer, or because a conditional expression yielded an integer value but should have been a boolean. It doesn't really matter which of these it is. It's simply that there are so many different ones that can happen.

But C++ is a great language and the last thing I would ever want to do is discourage anyone from learning it.

Swanny
You say "there are a ton of good C++ string classes". I don't know of any C++ string class that is better than the built-in std::string. Can you name some?
Hans Malherbe
Ah, that shows my C++ is dating. Is there a built in string now? I'm sure it will be very good. I had to use the MS CString in a lot of my more recent code. But one of my first exercises in C++ (1990 I think) was to write a string class. I've used Scott Ladd's one. Another I had to use was I think from Rouge Wave. C++ Builder had it's own AnsiString, and there were at least a couple of others. "ton" might have been an exageration, but it was a common example in many C++ texts back then.
Swanny
C++'s std::string is very usable, but badly designed in some ways. I don't know why; everybody who was on the Committee and has written about it has disparaged its implementation.
David Thornley
@Swanny: C++ has `std::string` since 98. The C++ as we know it today is much much different (and much more complex) than what it originally was and the last thing I would ever want to do is encourage anyone to learn it.
missingfaktor
@Hans: I find Qt's `QString` to be much better than `std::string`.
missingfaktor
+4  A: 

I think when people are saying C++ is hard, they are thinking that it's hard to master that language to the extent that they feel confident. They reality is that the more you learn about this language, the less you know. There always a better/fancier way in this very same language to re-implement what you have done as long as you do not give up. It's a beast you seem to never be able to kill. Well, the fact is you don't really have to IMHO.

On the other hand, with some other languages like python/C#, you will soon get to the point that you really know the language enough, all that's left is about familiarizing yourself with the library/APIs, and there's not much left to be squeezed inside the language itself; or at least you tend to feel so.

Like you just experienced yourself, if you only learn C++ to get things done in the common way(i.e. like people typically do with other languages ), rather than try to write the best possible code in terms of performance/style etc. C++ is really easy to learn.

another minor point is that, with C++ you need a little low-level thinking like pointers, memory allocation and collection, but that's trivial labor and the gain is great: you lay yourself a solid base for writing performant code.

t.g.
+3  A: 

There are already many good answers in this thread. Let me just add that C++ is a very flexible language that does not require (or even encourage) a developer to structure the code in any particular way. That is a blessing for an experienced programmer but a curse for a beginner. You'd better make sure you are learning the language from a good and recent book, or even better have an experienced C++ programer guide you and review your code.

Good luck!

Nemanja Trifunovic
I find that approach to thinking particularly helpful when a concept can't easily be described in terms of classes and their instances. I would hate to have to write a hello word class.
Hooked
+1  A: 

Any language with overloadable functions and operators is going to be harder to learn than a language without these features. Pointers and addresses are a known learning difficulty, plus there is a similar (but different) notation for references.

Code snippets in C++ often cannot understood until at least several header files are also read, and these need to be found- code navigation skills are always a barrier to learning for new programmers.

kmarsh
Java and C# both have overloadable functions, C# has overloadable operators.
Daniel Earwicker
+2  A: 

In fact, when I look at C# or Java code, it seems restrictive - why should I have to write a class to print "hello world?"

That's not restrictive at all. It's just a bit of extra boilerplate; it doesn't stop you doing anything at all.

In fact, it's not really true to say that you have to "write a class" in any creative sense. You don't have to think about it at all, and a decent IDE generates it for you anyway.

There are genuine ways in which Java and C# restrict you, but only from things like random access to the whole of memory or unchecked array access (same thing), that are generally only needed in realtime, embedded or kernel-mode programming, and not even always then.

(And in fact C# has an unsafe block feature in which you can do those things, so it's not really restricted at all, although it's best to avoid using them anyway.)

Once you've overcome the challenging hurdle (!) of dealing with:

public class App
{
    public static void Main(string[] args)
    {

    }
}

You should find that a lot of benefits begin to become apparent - especially in C#, which has a number of great features that Java lacks.

These are some of the things I've come to happily rely on since adopting C#:

  • rich reflection at runtime
  • runtime-type safety with no holes (disallowing casting between unrelated types)
  • dynamic libraries as a built-in concept
  • built-in garbage collection
  • bounds-checking at every level
  • a vast ecosystem of ready-to-use libraries designed to take advantage of all the above

And those are just the things that Java also has. In C# the functional style enabled by lambdas and iterator methods is like a different world of power and expressiveness altogether.

Daniel Earwicker
it is restrictive in that you aren't allowed free functions (meaning you have to write things like Math.Max() in c# or do static imports in java). Arguablly java's static imports are fine for this (since they make the class behave as if it was a namespace), and let reflection/debugging code keep their code paths clean but this is a real restriction on using c# in a script like fashion. which is fine for many people but you shouldn't pretend it doesn't exist, that's what makes language design such an interesting trade off
ShuggyCoUk
I completely agree that the abilty to at least simulate free functions would be handy in C#, but I can't make sense of calling it a "restriction". It doesn't stop you doing anything productive; it's just marginally more verbose. (And if you want to provide a set of methods to a C# "scriptlet", just put them in a base class of the wrapper class and they will be available as unqualified method names.)
Daniel Earwicker
It's a restriction, you can't do it and it fundametally restricts the usage of c# as a scripting language (this is something the c# designers are actively discussing/talking about in the context of hypothetical c# vNext's) http://209.34.241.67/ericlippert/archive/2009/06/22/why-doesn-t-c-implement-top-level-methods.aspx
ShuggyCoUk
Yeah, if you look at that blog post, I'm the first commenter on it, saying what a good idea it is. This does not, however, make it "restrictive". Having to put C. in front of a static method name (where C is the class name, and could be one letter) is not restrictive, merely inconvenient, and - I can only repeat this until it sinks in - there are already ways to make a set of methods visible to a script as unqualified names, including inheritance.
Daniel Earwicker
inconvenient *is* restrictive. If you achieve the desired syntax by inheritance you restrict any other base class (so all those useful free functions _must_ be in one class). If you pick a short name for the static class you stand more and more risk of colliding with a property name, restricting you. It's not a question of sinking in it's a question of perspective. From the point of view of using it in a scripting fashion this is actually very restrictive. From the point of view of a more common LOB app it's a non event. The perspective is everything.
ShuggyCoUk
Okay, here's some perspective: the questioner is comparing with C++, which isn't a scripting language.
Daniel Earwicker
true, in the context on initially learning it is easier to get someone to hello world in C++ than it is in java or c# because less (initially to the beginner) confusing verbiage needs to be provided bring up the inevitable 'what is a class', 'what is a namespace'. C++ has to have some bits that are easier than c# or java for the beginner somewhere :)
ShuggyCoUk
But in C++ you have "what is an include file?" and "What does << do"? and "What does :: mean?" And in any case, if a language makes Hello world easy (and I don't think C++ does), but everything else hard, that's not a great criterion to judge it by.
Daniel Earwicker
since you have include/using/import this is roughly a wash. I agree that << is less obvious than the alternates though it does mean you can skip string concat for simple examples. :: verses . only matters once you have some level of nesting, you can skip much of that to start with so is less of a big deal. I'm still of the opinion that C++ is way harder to pick up for beginners (see my answer) but I'm not saying _all_ aspects of it are. Especially if you initially don't care at all about OOP.
ShuggyCoUk
"not a great criterion to judge it by" -> I'm NOT judging the language. The specific question is why is it deemed harder for beginners to learn and I'm trying to answer why with no implication that this makes either better or worse, just easier to pick up. You could apply this to some really simplistic languages and say that learning, say, basic is much easier than C++/c#/Java. This would be true but obviously at the end of it you would be left with a much less powerful tool.
ShuggyCoUk
+6  A: 

Specific measurable differences compared to java and c#:

I am not in any way suggesting one approach or the other is better simply that they are different and that difference makes one or the other easier to pick up/learn/avoid bugs

Pointers

java/c# No raw pointers (c# none by default and even then very restricted) C++ pointers all over the place.

Pointers are not in simple terms overly complex, but they can rapidly combine in interesting (read hard to understand) different ways and they mean that common errors with them (running off the end of buffers for example) can have poor locality of error. So eventually you hit a bug/crash but that tends not to happen where the bug is, but in some, possible entirely unrelated, other part of the system.

If the code in question is new greenfield development it is possible to avoid many uses of pointers but many third party libraries assume their use.

Bounds checking

As alluded to above, buffer overruns due to a runaway pointer are impossible. As are invalid casts, writing to references which are no longer alive and a host of other possible accidental bugs.

Managed memory

In java you have no control over new whatsoever. It goes on some heap you have no control over (and thus cannot go wrong). You do not have to ensure it is deleted by the correct counterparty (delete/delete[]). In c# there is a slight amount of control (structs/stackalloc) but this is limited to very controlled areas which most c# developers probably never use.
There is no need to pass around the allocator when using templates that need to allocate.

Total reflection/introspection

In the managed languages you can, at runtime, inspect the structure of your entire object graph if desired. Even if a reference is via an object typed variable this doesn't stop you (and more importantly the debugger) knowing exactly what type the instance actually is.

Single inheritance (of implementation)

Multiple inheritance is rarely used and makes the reflection scenarios very complex.

strings are immutable and built in

For all that C++ now has std:string there is a still a vast amount of code out there expecting to deal with c style char pointer strings. The functions for working with these are tersely named, many have dangerous buffer overflows associated with them, some expect you to include the trailing null, others not.

The immutable strings in c# and java prevent many of these bugs ever happening and avoid many forms of memory leaks

standard method naming

C++ tends towards a terser method naming convention, c# and java towards a verbose one. This makes reading code for inexperienced readers considerably simpler.

Definition and declaration in one place

No header files, no confusion of what should go where and the compilation effects associated with it. Forward declarations perfectly legal and the compiler sorts it all out for you. The resulting error message in the simpler languages also tend to be better. The c++ pre-processor is incredibly powerful, but as a result can produce bewildering error messages.

Tooling

The newer statically typed languages tend to be pretty simple to parse robustly even when not fully completed. This makes the advanced IDE functions like intellisense and error highlighting more functional and responsive. Given the large size of modern standard libraries this is often very important to inexperienced developers.
The well structured introspection aspects of them also provide for more flexible design time scenarios.

Primitives

Fixed size integral, floating point, characters, you never have to be aware of your target hardware unless you are using IntPtr.
IEEE FP arithmetic is mandated.
Overflow can be detected automatically.
booleans are very well defined and no casts to/from them are allowed.

Common features built into the language (or Sugar!)

foreach - readable (IMO slightly less so in the java version) and removes off by one errors.
locking - though several of these can promote bad behaviour they are at least standardized.
Absolutely everything can be made to output a textual representation by default.
try/catch/finally simplifies much of the SEH code.

Conclusions

You will note that in many of the examples above c#/java prevents you doing something or only allows you to do it one, highly controlled, way. In this it is simpler to learn. C++, by being more general, has an inevitable additional cognitive load when wanting to do something which could be achieved by more than one available technique.

ShuggyCoUk
C++ does not in general need raw pointers, and resource allocation with RAII and smart pointers is more general than garbage collection. If you have to deal with existing code that uses pointers and char *, why is it easier to use C# than C++?
David Thornley
If you're dealing with existing code then of course changing to some other language almost always has a big -ve against it. What I'm saying is that I have used loads of supposedly C++ libraries from other vendors where they expect c-style strings. Thus you end up having to know about them (and their pitfalls)
ShuggyCoUk
C++ is more general (Implied in my conclusion). Writing good RAII code is harder than writing something that lets you forget about who is the owner of the result of new.Consider any program X which contains at least one allocation whose lifespan is neither stack nor instance bound. In C++ if you are not to to leak 1) Identify this, 2) wrap all access in a smart_ptr (picking the right one!). You simply don't need to do *either* of these things in c#/java. That this might be worse for the performance of the app is immaterial to the question in hand which is "why is C++ considered _harder_"
ShuggyCoUk
no longer implied in my conclusion - now explicit
ShuggyCoUk
A good interface is both easy to use and hard to use incorrectly. Although using RAII is more effort (for *memory*), it allows the safe use of classes without needing to inspect the implementation. On GC platforms, the user needs to inspect the class to see whether it must be disposed or not in order to use it safely. It's easy to forget or just use Intellisense, which does not always work like it should.
Hans Malherbe
The point about the consistency (needing to know which classes require disposal) is a good one but one can point out that, to a beginner this often doesn't matter and the two most common instances of this (Streams on files and database connections) are commonly identified in examples as requiring this. Deterministic disposal of local variables which require dispose would be an interesting addition to c# I think. That said forcing you to think about the usage of a limited resource is not always a bad thing.
ShuggyCoUk
I would say that, on balance, the ratio of memory deallocation code verses resource free code is skewed so far towards the former that, for beginners, the GC aspect wins in terms of ease of learning. Whether this is long term a good thing is a more complex question.
ShuggyCoUk
+1  A: 

I started with C++ and I don't see it as a bad thing either. Nor particularly hard. You don't HAVE to "write" a class to do a hello world (while console applications are set up with the "static class Program" by default, that doesn't really make it "writing a class", if that makes sense). I bet you don't even need to do that to actually get the program to work either, but I have never tried.

What makes C# "easier" I think is just the nature behind how it is set up and how much more is done for the programmer in terms of memory and management.

bdwakefield
+3  A: 

Well, there is definitely something to learning the fundamentals, being "hard", and then learning the simplified. Don't get me wrong, I've spent many many years of my life doing Java, and I've built a really nice lifestyle thanks to Java.

But in the end, everything on the computer eventually boils down to C/C++/asm at the lowest levels, and so I hold that it's good to have spent some time down there.

Plus, C++ gives you some job insurance considering many of these other languages are controlled by large companies. For example, everyone is holding their breath to see what Oracle does to Java, and MS has enough power to one day turn C# on its head and no one could do anything about it.

Additionally, it's similar to learning musical instruments: if you start with one that is very difficult, and learn it well, learning to play simpler instruments becomes trivial. (Specifics removed to avoid the flames).

All in all, obviously you're free to do what you want. It's possible to go an entire career (hopefully, given the state of CS education in the US at the moment), in Java, and never have to learn anything else. A guy can make a decent living at it after a number of years.

But let me say that you will never regret the time you spend learning the lower-level languages. It gives great appreciation of the mechanics of how things work, and you don't necessarily get that any other way.

JPDecker
+6  A: 

C++ is expert friendly.

This means that it is not a good language for a beginner who wants to get things done now.

However, it is a good language for someone who wants to write software that has high demands, e.g. the .NET JIT compiler or the next Unreal Tournament.

C++ has some features that make programming safer, like const correctness and deterministic destruction.

Contrast the viral nature of the C++ const operator with C# where you have to pass a copy of an array to the outside if you want to preserve encapsulation.

I suspect that many bad C++ experiences come from people that write C++ like C with classes. If you are using the new operator outside a ctor, printf or malloc you are probably on the wrong track.

What makes C# better for most is not the GC or the OO features, but the base class library.

Hans Malherbe
I would add that i don't think its the base class library per say, so much as the base class library being well defined, in one place, consistent and well documented. The STL + Boost is way better then any java or .net BCL but there is often overly complicated or overly general or lacking documentation(boost graph library comes to mind)
Hippiehunter
Things like XML, Web Services and GUI don't really have good solutions in C++. I agree though that the things that *are* covered in boost and STL are often more powerful than you'll find elsewhere.
Hans Malherbe
A: 

One reason is that C++ has many confusing features that are mostly useless:

  • Preprocessor.
  • Arrays.
  • Lots of parts of the C library, e.g. malloc(), free() and printf().
  • Structures.
  • Exception specifications.

Another reason is that many constructs were designed as if programmers never do mistakes:

  • Arguments' default value aren't showed in functions definitions.
  • Your destructors must explicitly be virtual. This makes many people write “memory leaks”.
  • You have to tell the compiler which methods don't modify this (those are allowed to be called on constant objects).
  • You have to keep track of memory yourself. The only sane way seems to be encapsulating pointers into objects which free memory themselves (“smart pointers”). To me it's like writing his own garbage collector, i.e. reinventing the wheel.

I've also noticed that programmers who misuse C++ generally are arrogant, and consider themselves as the “elite” of programmers. This is because C++ requires the programmer to be extremely careful and know a lot of details about the language. If the programmer just thinks she's great and doesn't need to learn, then she makes a lot of mistakes without even noticing them, and she doesn't understand why so many people find C++ difficult.

Bastien Léonard
Wow, I had no idea the preprocessor was useless. clearly every major C++ project has gotten this wrong and must bow to your infinitely arrogant knowledge.
Hippiehunter
“Mostly useless”.
Bastien Léonard
If they were mostly useless there wouldn't be so much use for them....
Hippiehunter
Much of these “features” are just there for compatibility with C, or to be able to achieve the same performance as in C. I don't see why the preprocessor is especially useful. One of the main complaints I hear about C++ is that headers make compilation time too long.
Bastien Léonard
At the very least, the preprocessor allows programmers to work around broken compiler implementations/platform differences. Granted most platform specifics have been abstracted away in one form or another but guess what they used to accomplish such a feat.... the preprocessor. Its not just for C, and its one of the features of C++ that it is important to use as little as possible yet when you need it, you absolutely positively need it.
Hippiehunter
This fits my definition of “mostly useless”. Even restricted to this simple use case, the preprocessor is clunky; it's not type-safe and it can't use `sizeof`. In C++ you want to use `const int` instead if `#define`, so to me it looks like it's only useful for header guards, compatibility with C and hacks.
Bastien Léonard
In C++, the preprocessor is useful for conditional compilation, the assert() macro, and little else. BTW, you don't have to declare destructors virtual if you're not going to delete object polymorphically. C++ often has several ways of doing things where Java and C# have more or less standard ways, and so in C++ you do have to keep track of some of these things.
David Thornley
+9  A: 

I hate to contribute to this question so late but I think there remains one important thing unsaid.

Languages like C++ are hard to learn “correctly” (whatever that means) and incredibly easy to learn wrongly: as a beginner with no experience, you will cut corners wherever possible and you'll do things contrary to design because you don't understand the reasons behind a (seemingly complex) design.

There's certainly not one right way to program C++ but there are just as certainly a gazillion wrong ways. Even worse, most learning resources out there are incredibly. evil. They are really that bad. They not only encourage bad, erroneous style, they teach it as canon. Declaring main with return type void may be one thing but not freeing resources (properly), not giving base classes virtual destructors, using polymorphic arrays, favouring void* to templates are just some things off the top of my head that most teaching books for C++ get, continually, wrong.

If you're learning C++ without proper guidance, you're easy prey to such dangerous practices and it takes year to unlearn these mechanisms. Having started with BASIC myself, I can testify to the destructive force of bad teaching material. Basically, the first three years of my learning to program were complete waste. Three lost years. Who's giving me a refund?

Konrad Rudolph
That three years may have been more valuable than you think. Learning to deal with complexity and spaghetti, and seeing first hand how things can deteriorate may have made you much more valuable. I think you should get out your checkbook and send Kemeny and Kurtz sizable gifts.
Nosredna
I don't think it can be over emphasised how much bad practice is taught for C++; and not just idioms that might have been necessary nearly 20 years ago.
Steve Gilham
+1  A: 

Because of all the 'hidden' features...

http://stackoverflow.com/questions/75538/hidden-features-of-c

Henry
A: 

I really like C++. It was my second language, and my first real language. I consider it my primary language(while knowing that there are Masters of C++, and I am not a master).

It's very complex, however, and if you dabble in the more complex areas while learning how to "think programming", you're going to have your feet cut from under you - repeatedly. There will be bugs, and you won't know why, or how to find out why, because you're a newbie.

I recommend Common Lisp for a first language, personally.

Paul Nathan
I thought lisp was totally unreadable. Is that a biased view (I heard it from a game programmer)?
Hooked
Lisp is confusing until you know what's going on. E.g.... instead of "i = a+ b", you'd have "(setq i (+ a b))". All operations are prefix instead of the typical infix. So the syntax is the simplest of any programming language. Scheme in particular is simple. Scheme doesn't have loops though, so I wouldn't recommend it for beginners.
Paul Nathan
Lisp is beautiful, but it can be very scary for beginners, I'd say even pretty difficult to learn without proper guidance. I think Python is a much better option as a first language... the bad thing is that you can like it so much that it could be also your last one! XD
fortran
Paul Nathan
+2  A: 

It's difficult to build a comprehensive list of "bad things" about C++, but some of the most important to me are :

  • Too big. That makes it harder to learn and most important, to read and maintain.
  • Some relevant things are done "under the hood" and can pass unnoticed if you're not careful (e.g. copy constructors).
  • It's not a strict superset of C (unlike Objective C, for example), which can lead to problems when you try to map previous knowledge from C or just try to port some code.
  • It gives a false impression of safety and "high levelness", which is very dangerous (at least with C you always know that you're walking in a minefield and that keeps you alert).

And of course, there are lots of other languages that usually fit better for the task at hand, C++ tries to be good for everything and that's just impossible.

fortran
A: 

C++ is not only a OOP language but a multiple paradigm language. A C program (imperative) usually compiles without problems with a C++ compiler. You can do Meta-programming of you walk the extra mile and use templates.

So YOU have to decide what purpose the language is used for. New programming languages (like C# or Java) are designed with a specific purpose in mind, like "work well with .NET" or "easy to learn and use". For C++ it is the other way round. NOT the language determines what it is used for but YOU decide what you use it for.

It does also does not run inside a virtual machine so you have to stick very close to the underlying platform you compile on.

+1  A: 

First of all, I wouldn't call it a BAD choice... That would be like saying that learning to drive a car with manual gear is a bad choice.

C++ is considered harder to use because when programming in C++, one has to take many things into consideration - Memory management for instance: If you program in Garbage collected languages, you wouldn't have to worry about memory allocation and disposal, but on the other hand, the control is taken away from you.

C++ is a powerful language, in which you can have full control over you code execution, and achieve great performance, but many of the features which can be taken for granted in Java or C#, aren't so in C++, and you'll have to write your own classes.

In summary, it's obvious that driving an automatic gear is easier, but race drivers drive cars with manual gear...

Gal Goldman
+1  A: 

Because once you are a beginner in C++ you also have to be a beginner with compilers, bitmasks, memory layout and management, vanilla C (that's what it comes down to), some asm (to understand what is actually going on), linkers (how else will your program do anything useful?) and in general to the way computer manages programs as opposed to how a human manages them. It's 80 percent "working around the system" and 20 percent learning to program in the traditional sense. Basically you jettison yourself into the vast ocean of warts of modern computing all at once. Dunno if that's best for a beginner.

Julik
+2  A: 

It is not that hard, you can learn it in 21 days!:

alt text

Comptrol