Learning C++ (for the right reasons)
Right, so there have been plenty of posts regarding technology choices, and how Unity/Game Maker what have you are the one true way. I tend to agree with these posts - starting from scratch in C++ is just madness if you're a single indie developer.
So here is my dilemma - from time to time there are opportunities that pass by me because I'm not proficient in C++, particularly in the international arena. So I would like to ask what a good starting place would be for an experienced programmer proficient in C# and many other languages?
Without a doubt I think the best way to actually "learn" a language is the throw yourself in the deep end and take on a project. I'm kinda hoping there are at least some approachable resources that outline the different design philosophies and working practices of the different languages so I can start familiarizing myself with C++. Also note, I'm not looking to learn about doing low level graphics and engine programming, more just to get an impression of what I'd actually be in for and what concepts I'd need to get my head around if say I was working a bespoke game engine. STL, malloc, templates, pointers and references. All that jazz.
So here is my dilemma - from time to time there are opportunities that pass by me because I'm not proficient in C++, particularly in the international arena. So I would like to ask what a good starting place would be for an experienced programmer proficient in C# and many other languages?
Without a doubt I think the best way to actually "learn" a language is the throw yourself in the deep end and take on a project. I'm kinda hoping there are at least some approachable resources that outline the different design philosophies and working practices of the different languages so I can start familiarizing myself with C++. Also note, I'm not looking to learn about doing low level graphics and engine programming, more just to get an impression of what I'd actually be in for and what concepts I'd need to get my head around if say I was working a bespoke game engine. STL, malloc, templates, pointers and references. All that jazz.
Comments
Theoretical C++ is all about coding conventions and what your program is actually doing, that's why lots of C++ courses start after some sort of Assembly module, then a C module, before getting to the extensions and object-oriented stuff. That's why C++ tends to always veer towards low level implementation angles - because that's what it gives you to work with, everything is unrolled and you have to decide how you want things to fit together.
In C++ everything is about memory. How you access it, what you want to do with it and where that memory actually is on the machine:
Pointers are memory addresses, how they behave depends on what is actually at the memory address they're pointing to: You can call a method on an object, if C++ has been told that it should expect an object at that location (that's what the pointer->method() notation does) if it's just a number at that address, then you can treat it like a number. That's why the type of a pointer is so important - it tells the language how much memory that pointer is actually "pointing to".
Referencing and dereferencing are tools to figure out if you should be paying attention to a variable's memory address or the contents of that memory. Finding the reference of a variable will give you back that variable's memory address, essentially giving you a pointer to it. De-referencing a pointer will give you the contents of that memory address, usually as a copy in a new variable (so hence new memory location). Most managed languages have similar constructs around passing parameters by reference (ref in C#) and value (dereferenced copy, val in C#). There are all sorts of different reasons to mess with these things, but generally if you have to it means that something is broken in the system design.
Malloc is there to give you access to chunks of memory. Dealloc nukes memory chunks. The "new" operator in C++ is essentially a custom malloc call that gives you enough memory to store the object you told it to give you, but it also finds a place to store that object. Because you're in direct control of all your memory, you have to make sure that you kill objects when they're not in use anymore, otherwise your memory needs will keep growing and horrible shit starts happening. Many people use malloc to create their own versions of garbage collection mini-implementations, so you might have X memory allocated for a particle system and maintain your own pointers for where new particle system objects should go inside that pre-allocated chunk.
Templates are a way to try and deal with shifting memory size requirements where they might not be known beforehand at the time of writing. Things like strings and arrays regularly cause havoc in C++, strings have no real "set size", so they need to have a special ending character, for instance. Templates basically allow you to write stuff independant of the size of a particular memory chunk, so you could write a template for a linked list and then fill in the thing that linked list is actually storing at run-time. Generics in C# are templates, so Unity's List<> is a template implementation.
So, working with C++ is all about keeping track of memory, having access to memory while debugging is super-important! If you can't step through your code and see how memory is actually changing in response, run far, far away... You have to destroy things and know how big things are, know where you're putting them and why you want them. That counts as much for variables as it does for object storage. One of the biggest issues you'll have with a C++ program is doing the equivalent of keyhole surgery in a chunk of memory somewhere, except you're operating on a brain when you thought you were fixing a knee problem, so everything goes horribly wrong. That's why a lot of C++ architecture rambling talks about making sure you can't poke memory you shouldn't be able to poke - Const and dereferencing and protective casting and all that jazz.
Then there's all the stupid pre-compiler stuff that gets horribly annoying, I would ignore most of those as showing off, especially the one-line if bullshit. The only exception is headers. Header files are essentially instructions for the compiler so that it can know what you're going to be populating with code later on, it's almost like a sizing chart for your program combined with a cheat-sheet so that you can call other methods without your compiler going "but that doesn't exist yet!".
Full-contact C++ is pretty much just like the above, except you're fitting into an existing system as quickly as possible. That means there will be code guidelines already in place, if they don't have a standards document, don't touch the project. That also means that there's probably a stricture against using new, under pain of death. And you might not get shot for using void pointers if you're not a complete lunatic with them.
But yeah - it's all about memory.
As for possible corrections, I've heard generics are fundamentally different from templates - but that is just incidental hearsay. I'm sure there is enough similarity to warrant the comparison.
A couple of other details you should be aware of. In C++ you can pass objects by pointer or create copies (the compiler will copy your class but does not do a deep copy so it can be troublesome). In most type safe languages you can not conveniently copy objects or structures. C++ organizes all classes and structures so you can simply copy the memory to a new location and you have a shallow copy of that object. (shallow meaning that if you had a pointer in that object to another the inner object is not copied only the pointer to is.)
Essentially C++ memory management is your problem. this guide gives you a fair overview. http://en.wikibooks.org/wiki/C++_Programming/Memory_Management
I release both Toxic Bunny HD and The Tainted both written in C and C++ and assembler mind you. There are some really neat tricks you can implement and you really can feel like a programming genius when you pull off the simplest of things. The memory management got to the point where we overloaded the new and delete methods of the sprite classes to assist with fragmentation of the heap.
As @dislekcia pointed out you have to manage who owns what since any thing you use the new keyword or you malloc directly must be deleted when you are done with it. This requires you work in pasterns of ownership. Say a function you are calling requires a buffer. Consider this example. You call a method that loads an image and returns it to you. Now you have this chunk of memory that belongs to your code. How will you manage the scope of that memory what functions or objects will be responsible for deleting it when its no longer needed. You have to design your solution so that you can clearly identify when objects go out of scope and delete them when that happens.
If you decide to do a project would love to see what and how it goes, I for my part love working in c++ but I don't have projects that really require that kind of control or can justify that kind of cost.
But C++ has of course many other ways of screwing you around. The other thing that still scares me a little is how incredible difficult it can be to make certain design changes. I had many instances where C++ + my_own_cleverness == nightmare_from_hell. C++ is definitely the language where more upfront thinking and design is incredibly useful. This is also why a real-project is a good way to learn; those mistakes are useful to make. But like @tbulford said, it is a language that _does_ you make you feel clever, and I did get a lot of satisfaction from it.
The one resource that became my bible is Bruce Eckel's Thinking In C++ (freely downloadable). (Are they a bit old now?)
One other recommendation I can make is to look at a library or two relevant to the type of programming you do, and write some code on top of that, to get into it, perhaps, before starting an actual project. This will give you two important pieces information: First, a feel for the C++ compilation + integration process, which is by far the most complex of any language I worked with. Second, a feel for how to organise your code [architecturally] / data structures, and indeed, memory responsibilities.
Anyways, good luck, and have fun :)
Also... Dear god please use the new smart pointers! Every C++ developers lives have changed drastically by using them. Sure you should learn pointers and how to manipulate memory but 99% if the time using a shared pointer will just make everything *so* much better.
[Edit:] You have no idea how passionate I am about C++11... It really has changed my life <3 (well when i can't use *any* other language that is :P)
@creative360 sounds great, but how interoperable is C++11? Assuming the whole environment has to be written in it?
@Elyaradine That's pretty good advice in general, boost have many extensions which make life a little easier. A few of the C++11 standards were implemented in boost before the new standard came out (like the smart pointers). Personally I've never really used boost so I can't really talk about it with conviction.
https://www.coursera.org/course/cplusplus4c