Object Oriented Programming (OOP) is a way to integrate with objects which can contain data in the form (attributes or properties of objects), and code blocks in the form of procedures (methods, functions of objects). These attributes and methods are variables and functions that belong to the class – part of the class’s code and they are generally referred to as class members. Classes and structs are very useful in modern programming. There are some rules to support the principles of programming, one of which is the Rule of Zero in C++. In this post, we explain what is Rule of Zero in C++ with examples.
Table of Contents
What is resource acquisition in C++?
The principle of Resource Acquisition Is Initialization (RAII) term used in several OOP programming languages, which relates to the ability to manage resources, such as memory, through the copy and move constructors, destruction, and assignment operators. RAII is about the declaration and use of destructors, copy-move operators, and memory management in these members and methods. These cause new rules in development.
What is the Single Responsibility Principle in C++?
The Single Responsibility Principle (SRP) is a computer programming principle that states “A module should be responsible to one, and only one, actor.” This principle exposes a rule for the classes in C++, called Rule of Zero. Now, let’s see what the Rule of Zero in C++ is.
What is the Rule of Zero in C++?
Rule of Zero means that, if all members have default member functions, no further work is needed. This is the simplest and cleanest semantics of programming. The compiler provides default implementations for all of the default member functions if there are no special member functions that are user-defined. In other words, you should prefer the case where no special member functions need to be defined. In this rule, classes that have custom destructors, copy/move constructors, or copy/move assignment operators should deal exclusively with ownership; other classes should not have custom destructors, copy/move constructors or copy/move assignment operators.
Rule of Zero helps simplify our C++ code without risking resource management issues at run time. The term The Rule of Zero was coined by R. Martinho Fernandes in his paper in 2012. This paper is highly recommended reading to get the full details of this concept.
The Rule of Zero rule can be seen in the C++ Core Guidelines here C.20: If you can avoid defining default operations, do. As in the example below, std::map
and std::string
have all the special functions, so you don’t need to create a constructor and destructor for them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Tmy_map { public: // ... no default operations private: std::string title; std::map<int, int> coords; }; Tmy_map m; // default construct Tmy_map m2 {m}; // copy construct |
How can we apply the Rule of Zero in C++?
Here are some notes as to-dos in Rule of Zero.
- A simple empty C++ class is perfectly equivalent to default implementations (Rule of Five) in a class. A modern compiler is able to provide a default implementation, in example, this simple class.
1 2 3 4 5 6 |
class Tx { }; |
This class is exactly the same as the one below in modern C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Tx { public: Tx() = default; Tx(Tx const& other) = default; Tx& operator=(Tx const& other) = default; Tx(Tx&& other) = default; Tx& operator=(Tx&& other) = default; ~Tx() = default; } |
- Use a
std::unique_ptr
if your class can be moved but should not be copied. - Use a
std::shared_ptr
if you need to support copying as well as moving. - Use
std::string
,std::wstring
or otherbasic_strings
over arrays of characters, they support both copying and move semantics. - Use Standard Library container classes. Prefer to use
std::vector
,std::map
std::array
etc.
Is there an example of the Rule of Zero in C++?
Here is a simple C++ example of the Eule of Zero in C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <iostream> #include <string> class Tzero // Rule of Zero Example { private: std::string str; public: Tzero(const std::string& s) : str(s) { std::cout << s << std::endl; std::cout << str << std::endl; } }; int main() { Tzero z("LearnClusPlus.org"); system("pause"); return 0; } |
If this base Tzero
class is intended for polymorphic use, its destructor may have to be declared public and virtual. This will not allow implicit moves, deprecates implicit copies. Thus, the special member functions have to be declared as defaulted as in base declarations of five defaults. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Tfive { public: Tfive(const Tfive&) = default; Tfive(Tfive&&) = default; Tfive& operator=(const Tfive&) = default; Tfive& operator=(Tfive&&) = default; virtual ~base_of_five_defaults() = default; } |
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.