What I Learned from Scott Meyers' Effective C++, Part 2

Chapter 2: Constructors, Destructors, and Assignment Operators

In my previous chapter we discussed accustoming oneself to C++ in the first 4 items of the book. In this chapter, we'll talk about what I learned in chapter 2 of the book, items 5 to 12.

Item 5: Know what functions C++ silently writes and calls

When a class is created in C++, the compiler may create some default utilities for you. These are the default constructor, destructor, copy constructor and copy assignment operator. It is important to know this detail and implement your own versions to ensure the correctness of your class behaviour.

Item 6: Explicitly disallow the use of compiler-generated functions you do not want

There are cases where you'd like to disallow some default functionalities of a class provided by the compiler. Such as disallowing copying a class. You can achieve this by declaring that private and not providing an implementation.

Item 7: Declare destructors virtual in polymorphic base classes

Polymorphic base classes, classes you intend to derive from should declare their destructors virtual, in fact, any class with a virtual function should also declare a virtual destructor. This ensures correct polymorphic behaviour within derivations of classes and saves you from certain types of nasty bugs you could encounter. On the opposite side of the scale, classes not intended to be used as a base class should not declare virtual destructors as well.

Item 8: Prevent exceptions from leaving destructors

Ensure that your destructors are exception-safe. If necessary, provide additional cleanup methods(non-destructor) for client-side usage so that clients can handle possible exceptions. Emitting an exception in the destructor is likely to cause undefined behaviour and early program termination. If there are any calls within the destructor that may throw exceptions, ensure that the destructor either swallows the exception properly or terminates the program

Item 9: Never call virtual functions during construction or destruction

Virtual functions never go further down the inheritance chain than the currently executing constructor or destructor. Calls like this may try to access undefined members and cause a program crash. Unlike C# or Java calling virtual functions during construction or destruction will most likely yield undefined behaviour and should be avoided.

Item 10: Have assignment operators return a reference to *this

Having your assignment operators return a reference to *this lets you chain assignment operators and write more readable code. This also follows the convention of STL types, providing consistent behaviour throughout your codebase.

Item 11: Handle assignment to self in operator=

C++ allows you to self assign variables. It is up to you to ensure the behaviour is correct when this occurs. You can compare addresses of the source and target objects, order your statements carefully or copy and swap the objects for example. Pick your poison. It is also possible to refer to the same object with different symbols. Again it is up to you to ensure that a function operating on multiple objects behaves correctly if multiple of the objects are the same in reality.

Item 12: Copy all parts of an object

Copying behaviour can cause a lot of headaches if not carefully implemented. It is important to copy objects fully to avoid undefined behaviour or incorrect copies. Make sure that your copy assignment and copy constructors perform a deep copy instead of a shallow copy and also make sure that any other classes that compose the class you're copying do the same. If possible provide common functionality methods for your copy constructor and copy assignment operator to avoid code duplication.

That's it for this chapter, next article will be about Chapter 3, Resource Management