I'm currently teaching myself C++. I'm very proficient at C#, and was wondering which common practices in C# can lead to difficulties in C++, and what a C++ programmer should do instead.
The first and foremost, you must learn RAII: Resource Acquisition Is Initialization
Make sure if you use
new, then don't forget to use
deletein your program. Don't mix
mallocare not interchangeable, nor are
free. As in C#, you don't write destructor (usually), so in C++ you specifically need to learn how to use destructor effectively to free memory, and other resources! Once you know these concepts, try to design things in RAII-way to effectively handle resources, so that you dont have to deal with
deleteexplicitly in your code everywhere.
Must learn what is sequence points, undefined-behavior, unspecified-behavior, implementation-defined behavior in C++. As C# doesn't have these concepts, that means you've never heard these terms while programming in C#, so it's very very very likely that you'll write C++ code (such as
i+=++i) whose behavior is not well-defined. So I would recommend you to read these topics:
- Read items from Effective C++ Series by Scott Meyers. After them, read also Exceptional C++ Series by Herb Sutter.
PS: Since I talked about new, delete, raw memory etc, then let me add an interesting difference between C++ and C# :
this is a pointer, while in C#
this is a reference!
The most fundamental one is of course related to the lack of a garbage collector:
newany more than necessary. Understand the RAII idiom: allocate your objects on the stack (without using
new), and let their destructors take care of cleaned up allocated memory for you. Or use smart pointers to handle some of this for you.
Other than that, I'd say there are some stylistic issues you should get used to. C# is still, despite its flirtation with functional programming, an OOP language.
C++ is a multi-paradigm language, and in modern C++, OOP just doesn't play a very big role. You should definitely look into generic programming, though. Understand how to use the STL (the data structures, iterators and algorithms in the standard library). And feel just a bit dirty when you write a virtual function.
Automatic memory management and garbage collection is probably something you could be missing in C++. But IMHO what you will miss most is the consistency of the .NET framework where you have been taking lots of things for granted simply because they are built into the BCL.
The biggest problem I've seen is the tendency to new objects all over the place and use them on the heap. Sure, they may take a lot of care deleting them as there's no GC, but the problem is allocating on the heap in the first place. C++ works better putting stuff on the stack and copying it about. If you do still need a single shared object, use shared_ptr to contain it.
Mind you, this isn't exclusive to C# devs, I've seen a a few web devs do the same kind of thing.
Garbage collection is a big one, but if you use smart pointers you can avoid most of the trouble with that.
A more pervasive issue is that of exception safety. This isn't so much a C# habit that will get you in trouble, but a lack of one. In C#, you get safety with
using blocks and
finally handlers. C++ has neither. What you have is a technique called RAII (resource acquisition is initialization), where classes are carefully designed so that their destructors clean things up. So rather than use a
using block to open a file, you'll stack-allocate the file object and the destructor will flush and close the file. It takes care to design and use classes in this way, but once you form the habit your code can be pretty safe. It's just a different approach. In general, the fact that C++ has stack allocation of objects will necessitate some adjustment.
Be wary of
string types in C++, they have grown up from many years of (bitter) experience and there are different types. In C# they're all Unicode (I forget the encoding), but in C++ a
char is usually dependent on the system's code page. For example, US-English Windows uses a code page of Windows 1252 by default for non unicode programs. Code pages are difficult to manage and error prone so use
wchar_t and the STL's
std::wstring. Also be aware that the size of
wchar_t is different between different compilers. Many Linux based C++ compilers use a different character size and the advice is different again! See https://stackoverflow.com/questions/4588302/why-isnt-wchar-t-widely-used-in-code-for-linux-related-platforms for more info.
Be aware of the scope of variables and when they will be destructed. It is generally bad practice to do
return new object() as the caller might not realize they need to clean up the return value.
Learn about move semantics - they can help a lot with RAII. I'm not aware of an equivalent in C#
Understand what an opaque pointer is. If you're using the Windows API you'll come across a lot of these in the form of
Be wary of storing lists (e.g.
std::deque) of objects which can be inherited as this can lead to slicing where the inherited part of the class is sliced off so only the declared type is left.
Forget about try-(catch-)finally and get used to do resource allocation/deallocation via constructors/destructors (RAII).
Avoid programming in C++ as if it was C#, that's the practice you should avoid. Actually learn the language, it's quirks, the good parts and it's idioms.
The most obvious would probably be taking garbage collection for granted. Un-referenced objects have to be manually disposed in C++, but in C# you have the GC to take care of them.
Memory management, passing conventions and pointers, although if you use a library like Boost it's probably less of a problem. However, if you're teaching yourself C++ it's probably a good idea to not use any libraries and learn the basics first.
Memory management, watching out for memory leaks and getting used to not having automatic garbage collection.