What are some C++ related idioms, misconceptions, and gotchas that you\'ve learnt from experience?
An example:
class A
{
public:
char s[1024];
cha
Nothing I actually came across while programming, but a friend wanted an explanation on why the code worked. It took me a while to figure it out. Maybe it is obvious to you guys, but I am not an experienced programmer.
#include <iostream>
using namespace std;
int& strangeFunction(int& x){return x;}
int main(){
int a=0;
strangeFunction(a) = 5; //<------- I found this very confusing
cout << a <<endl;
return 0;
}
A few things that usually trip people up:
std::cout << a << a++ << --a;
i = ++i;
The above lines are both undefined.
void foo(bar* b1, bar* b2);
int main() {
foo(shared_ptr<bar>(new bar()), shared_ptr<bar>(new bar()));
}
The above may leak memory.
int* arr = new int[10];
arr + 11;
This results in undefined behavior.
As for idioms, my favorite is RAII. Allocate objects on the stack, which guarantees that the destructor is called when the object goes out of scope, preventing resource leaks.
I can't say that I am an experienced C++ programmer but I have recently learned how hard it is to pass and array of arrays as a function parameter. Try to avoid this at all cost :(
If you know the size at compile its simple. Even if you know one of the dimensions at compile time. If you simply don't know... you might be looking at something like this
m[i*dim2+j]
Being i the iterator for the rows, dim2 the number of cols and j the iterator for the cols.
Do not prefer to use shared_ptr
unless needed. Prefer using C++ references and unique_ptr
instead. shared_ptr
is a performance hog and makes the code look more complex than it is. Normally this won't be an issue, except for the unusual attractiveness of shared_ptr
and its contagious nature.
You don't need to know C++'s complicated function typedef declaration syntax. Here's a cute trick I found.
Quick, describe this typedef:
typedef C &(__cdecl C::* const CB )(const C &) const;
Easy! CB is a pointer to a member function of class C accepting a const reference to a C object and returning a non-const reference to a C object. Oh, and it’s a const member function. Oh, and the function pointer itself is const… (Right?)
The C++ function declaration specification syntax is notoriously obtuse and hard to remember. Yes, there are tricks seasoned C++ veterans may use to decipher such horrors, but that’s not what this tip is about. This tip is about how you don’t need to remember this horrible syntax and still be able to declare such function pointer typedefs (e.g. in case you’re interacting with some legacy API that never heard of boost::function). Instead of breaking a mental sweat, let the compiler do the work for you. Next time you’re trying to create a typedef to a member function that looks like this:
struct C {
const C& Callback(const C&) const { }
};
Instead of struggling to manually come up with the complex syntax above, induce an intentional compilation error which will force the compiler to name the beast.
For example:
char c = &C::Callback;
The compiler happily spews this helpful error message:
“… cannot convert from 'const C &(__cdecl C::* )(const C &) const' to 'char'”
Which is what we’re looking for. :)
Do not fall into the trap of using std::noncopyable
unless needed. Yes, it is useful at a lot of places, and should be used there.
The trap is that one starts writing clone()
function along with making it noncopyable, which implements the same functionality. Instead, you can also use explicit
(link) for the copy constructor instead to prevent accidental copying (and make assignment private, or delete the function in C++0x). clone()
is needed for inherited base classes though.