The default function in C++11

For the default function supported in the C++ 11 standard , the compiler will automatically generate a default function definition body for it, so as to obtain higher code execution efficiency, and it can also save the programmer from the workload of manually defining the function.

C++ classes have four types of special member functions, they are:

  • Default constructor
  • Destructor
  • Copy constructor
  • Copy assignment operator

The special member functions of these classes are responsible for creating, initializing, destroying, or copying objects of the class. If the programmer does not explicitly define a special member function for a class, and the special member function needs to be used, the compiler Will implicitly generate a default special member function for this class. E.g:

Listing 1

class X{
    
    
private:
	int a;
};

X x;

In Listing 1, the programmer does not define the default constructor of class X, but when creating an object x of class X, the default constructor of class X needs to be used. At this time, the compiler will implicitly refer to the class X generates a default constructor. The automatically generated default constructor has no parameters and contains an empty function body, namely X::X(){ }. Although the automatically generated default constructor has only an empty function body, it can still be used to successfully create an object x of class X. Listing 1 can also be compiled.

However, if the programmer explicitly customizes a non-default constructor for class X, but does not define the default constructor, a compilation error will appear in Listing 2:

Listing 2

class X{
    
    
public:
	X(int i){
    
    
	a = i;
	}
private:
	int a;
};

X x; // 错误 , 默认构造函数 X::X() 不存在

The reason for the compilation error in Listing 2 is that class X already has a user-defined constructor, so the compiler will no longer implicitly generate a default constructor for it. If you need to use the default constructor to create objects of the class, the programmer must explicitly define the default constructor. E.g:

Listing 3

class X{
    
    
	public:
	X(){
    
    }; // 手动定义默认构造函数
	X(int i){
    
    
	a = i;
	}
	private:
	int a;
};

X x; // 正确,默认构造函数 X::X() 存在

As can be seen from Listing 3, the default constructor that was originally expected to be automatically generated by the compiler needs to be manually written by the programmer, that is, the programmer's workload has increased. In addition, the code execution efficiency of the manually written default constructor is lower than that of the default constructor automatically generated by the compiler. The other types of special member functions of the class are also the same as the default constructor. When there are user-defined special member functions, the compiler will not implicitly automatically generate the default special member functions. Instead, programmers need to write them manually. The workload of the programmer is reduced. Similarly, the code execution efficiency of the manually-written special member function is lower than that of the special member function automatically generated by the compiler.

To solve the two problems shown in Listing 3:

  1. Reduce the programmer's programming workload;
  2. Obtain high code execution efficiency of the default special member function automatically generated by the compiler

The C++11 standard introduced a new feature: the default function. The programmer can declare =default;the function as a default function by simply adding it after the function declaration, and the compiler will automatically generate the function body for the explicitly declared default function. E.g:

Listing 4

class X{
    
    
public:
	X()= default;
	X(int i){
    
    
	a = i;
}
private:
	int a;
};

X x;

In Listing 4, the compiler will automatically generate the default constructor X::X(){}, which can achieve higher code efficiency than the default constructor defined by the user.

The Default function feature only applies to the special member function of the class, and the special member function has no default parameters . E.g:

Listing 5

class X {
    
    
public:
	int f() = default; // 错误 , 函数 f() 非类 X 的特殊成员函数
	X(int) = default; // 错误 , 构造函数 X(int, int) 非 X 的特殊成员函数
	X(int = 1) = default; // 错误 , 默认构造函数 X(int=1) 含有默认参数
};

The Default function can be defined in the class body (inline) or outside the class (out-of-line). E.g:

Listing 6

class X{
    
    
public:
	X() = default; //Inline default 默认构造函数
	X(const X&);
	X& operator = (const X&);
	~X() = default; //Inline default 析构函数
};

X::X(const X&) = default; //Out-of-line default 拷贝构造函数
X& X::operator = (const X&) = default; //Out-of-line default
// 拷贝赋值操作符

In the C++ code compilation process, if the programmer does not define a destructor for class X, but needs to call the destructor of class X when destroying the object of class X, the compiler will automatically and implicitly generate a destructor for the class Destructor. The automatically generated destructor has no parameters and contains an empty function body, namely X::~X(){ }. E.g:

Listing 7

class X {
    
    
private:
	int x;
};

class Y: public X {
    
    
private:
	int y;
};

int main(){
    
    
	X* x = new Y;
	delete x;
}

In Listing 7, the programmer did not define a destructor for the base class X and the derived class Y. When the base class pointer x is deleted in the main function, the destructor of the base class needs to be called. Therefore, the compiler will implicitly and automatically generate a destructor for class X, so that it can successfully destroy the base class sub-object (that is, the int type member variable x) in the derived class object pointed to by x.

However, this code has a memory leak problem. When using the delete statement to delete the pointer x to the derived class object, the system calls the destructor of the base class instead of the destructor of the derived class Y. Therefore, compile The device cannot deconstruct the int type member variable y of the derived class.

Therefore, under normal circumstances, we need to define the destructor of the base class as a virtual function. When the delete statement is used to delete the base class pointer to the derived class object, the system will call the corresponding destructor of the derived class (to achieve polymorphism ) To avoid memory leaks. However, the destructors implicitly and automatically generated by the compiler are all non-virtual functions, which requires the programmer to manually define a virtual destructor for the base class X, for example:

Listing 8

class X {
    
    
public:
	virtual ~X(){
    
    }; // 手动定义虚析构函数
private:
	int x;
};

class Y: public X {
    
    
private:
	int y;
};

int main(){
    
    
	X* x = new Y;
	delete x;
}

In Listing 8, since the programmer manually defined the virtual destructor for the base class X, when the delete statement is used to delete the base class pointer x pointing to the derived class object, the system will call the corresponding destructor function of the derived class Y (by The compiler implicitly generates automatically) and the destructor of the base class X, thereby completely destroying the derived class object, which can avoid memory leaks.

However, in Listing 8, the programmer needs to manually write the definition of the virtual function of the base class (even if the function body is empty), which increases the programmer's programming workload. What's more worth mentioning is that the code execution efficiency of the manually defined destructor is lower than that of the destructor automatically generated by the compiler.

In order to solve the above problems, we can declare the virtual destructor of the base class as the default function, so that the compiler can be explicitly specified to automatically generate the function body for the function. E.g:

Listing 9

class X {
    
    
public:
	virtual ~X()= default; // 编译器自动生成 default 函数定义体
private:
	int x;
};

class Y: public X {
    
    
private:
	int y;
};

int main(){
    
    
	X* x = new Y;
	delete x;
}

In Listing 9, the compiler automatically generates a virtual destructor virtual X::X(){}, which has a higher code execution efficiency than the virtual destructor defined by the user.

Guess you like

Origin blog.csdn.net/u013318019/article/details/113894153