Why initalise in the constructor when it will be initalised in the code?
So that the implementation is exception safe. Suppose that you'd have this code:
SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock((QToolButton*)(0x0BEEF)), executingDialog(false) {
throw std::exception();
padLock = new QToolButton;
}
The destructor will delete padLock
, but it has junk value, and you have undefined behavior. Recall that deleting a nullptr is safe (as is calling free(NULL)
in C!). The junk padlock value shows what happens when you don't initialize it. Throwing demonstrates that some intervening code may throw. Specifically, any intervening new
will throw if the allocation can't succeed. new
does not return on failure (as in: it throws std::bad_alloc
instead of returning, so the notion of return value doesn't apply at all).
If one is writing idiomatic C++, then the pointer should not be a naked pointer, but a std::unique_ptr
or QScopedPointer
, and then this problem vanishes. You don't have to remember to initialize the pointer to zero, and you don't have to remember to clean it up. RAII gives you a lot of win. That's the secret weapon that you get when you really use C++ the way it's meant to be used.
The C++ RAII idiom doesn't exist per se in any other common programming language. In languages that allow it (such as Java, C#, F#, Python, OCaml, and Common Lisp), the idiomatic work-around is to define a higher-order with_resource
function, see examples for OCaml, Java and Python and Python again. Basically, in languages other than C++, and especially in garbage-collected languages, memory resource deallocation is handled differently from non-memory resource deallocation. In C++, those are united under the RAII umbrella.