C++ Explicitly defaulted function
前言
本篇基於Explicitly Defaulted and Deleted Functions in C++ 11,並加上TensorRT中的例子做為參考。
Explicitly defaulted function
從C++11開始,可以在函數後面加上= default
指示詞,使它成為explicitly defaulted function。如此一來,編譯器就會為這些函數生成默認的實作。
參考以下的例子:
class A {
public:
A() = default;
A(int){};
};
// driver program
int main()
{
A a1(0);
A a2;
return 0;
}
我們定義了接受一個參數的建構子,並用= default
的方式來定義另外一個無參數的建構子。編譯器會自動生成無參數建構子的body(空的),所以以上代碼可以編譯成功。
如果我們試著把A() = default;
注釋掉,然後再重編一次呢?這將導致編譯時在A a2;
這行出現錯誤:
error: no matching constructor for initialization of 'A'
並出現以下提示:
note: candidate constructor not viable: requires 1 argument, but 0 were provided
A(int){};
^
如果我們沒為A
定義任何建構子,則編譯器會自動生成默認實作的建構子。
但是在已經定義了一個建構子的情況下,編譯器就不會自動生成建構子,所以它只找得到需要一個參數的A(int){};
,但是A a2;
這一行並未提供參數,所以才會報錯。
Special member function
如果我們嘗試在以下函數後面加上= default
:
int func() = default;
A(int, int) = default;
A(int = 0) = default;
A(int) = default;
都會造成同一個編譯錯誤:
error: only special member functions may be defaulted
這是因為= default
只能被加在"沒有默認參數"的"special member function"後面,使它們成為defaulted function。
根據Special members,Special member function包含:Default constructor
, Destructor
, Copy constructor
, Copy assignment
, Move constructor
, Move assignment
等6個函數。
= default v.s. {}
注意到以下寫法:
A(){};
的表現與A() = default
是一致的。
那麼為何= default
的寫法是比較被建議的呢?原因有以下兩點:
-
使用
= default
可以讓你的class仍然是aggregate或是trivial type。 -
參考Special members的
Implicit members
章節,Copy constructor
,Copy assignment
,Move constructor
,Move assignment
這四種函數不像Default constructor
及Destructor
,它們的默認實作皆有意義。所以對於這四個函數來說,{}
與= default
並不是等價的。
在TensorRT中的例子
在TensorRT/parsers/caffe/blobNameToTensor.h
中為IBlobNameToTensor
這個類別宣告了一個虛擬的destructor:
class IBlobNameToTensor
{
//...
protected:
virtual ~IBlobNameToTensor() {}
};
在TensorRT/parsers/caffe/blobNameToTensor.h
中,BlobNameToTensor
繼承了IBlobNameToTensor
,為它的子類別:
class BlobNameToTensor : public IBlobNameToTensor
{
public:
//...
~BlobNameToTensor() override = default;
};
BlobNameToTensor
裡宣告了一個destructor,用於override其父類別的destructor,它並且還它被設為defaulted。
參考連結
Explicitly Defaulted and Deleted Functions in C++ 11
Trivial, standard-layout, and POD types
How is “=default” different from “{}” for default constructor and destructor?
Quick Q: How is “=default” different from “{}” for default constructor and destructor?
Overriding the default constructor/destructor without implementing them
default override of virtual destructor
What does “default” mean after a class’ function declaration?