当前位置:网站首页>Tips for this week 131: special member functions and ` = Default`
Tips for this week 131: special member functions and ` = Default`
2022-07-07 17:57:00 【-Flying crane-】
As totw#131 Originally published in 2017 year 3 month 24 Japan
from James Dennett ([email protected]) A literary creation
from the beginning ,C++ It supports the compiler declaration version of some so-called special member functions : Default constructor 、 Destructor 、 Copy constructor and copy assignment operator . C++11 Added move construction and move assignment to the list , And added syntax (=default and =delete) To control when these default values are declared and defined .
=default What's the role , Why do we use it ?
Write =default We tell the compiler “ What you usually do for this special member function ” The way . Why should we do this instead of writing the implementation manually or having the compiler declare one for us ?
- We can change the access level ( for example , Make constructors protected rather than public ), Make the destructor virtual , Or restore the function that will be suppressed ( for example , Default constructor for classes with other user declared constructors ) And still Let the compiler generate functions for us .
- If you copy / Moving members is enough , Compiler defined copy and move operations do not need to be maintained every time members are added or deleted .
- The special member functions provided by the compiler can be unimportant ( When all the operations they call on themselves are unimportant ), This can make them faster 、 More secure .
- Types with default constructors can be aggregated , Therefore, aggregation initialization is supported , Types with user supplied constructors cannot .
- Explicitly declaring a default member provides us with a place , Used to record the semantics of the result function .
- In class templates ,=default It's a simple way , To conditionally declare operations , It depends on whether some basic types provide it .
When we use =default when , The compiler will check whether it can synthesize inline definitions for this function . If possible , It just goes on . If not , This function is actually declared deleted , Like we wrote =delete equally . This is exactly what we need to transparently wrap classes ( for example , If we are defining a class template ), But readers may be surprised .
If the initial declaration of the function uses =default, Or if the compiler declares a special member function that is not declared by the user , Will derive the appropriate noexcept standard , This may allow faster code .
How does it work ?
stay C++11 Before , If we need a default constructor or have other constructors , So we can write like this :
class A {
public:
A() {
} // User-provided, non-trivial constructor makes A a non-aggregate.
};
from C++11 At first we have more choices :
class C {
public:
C() = default; // misleading: C has a deleted default constructor
private:
const int i; // const => must always be initialized.
};
class D {
public:
D() = default; // unsurprising, but not explicit: D has a default constructor
private:
std::unique_ptr<int> p; // std::unique_ptr has a default constructor
};
obviously , We should not write classes C Code like that : In non template , Only if you want this class to support this operation ( Then test whether it supports ) Use only when =default. clang-tidy Including the inspection of this .
After the first declaration of a special member function ( That is, outside the class ) Use =default when , It has a simpler meaning : It tells the compiler to define functions , And give an error when it is impossible to do so . When used outside the class =default when , The default function will not be trivial : Trivial is determined by the first statement ( So all clients agree whether the operation is trivial ).
If you don't need your class to be an aggregate and you don't need a constructor, it's trivial , Then the default constructor outside the class definition , Consider the following example E and F, It's usually a good choice . Its meaning is clear to readers , And checked by the compiler . For special cases of default constructors or destructors , We can write {} instead of =default, But for other default operations , Compiler generated implementations are not so simple , For consistency , It is best to write in all applicable cases =default.
class E {
public:
E(); // promises to have a default constructor, but...
private:
const int i; // const => must always be initialized.
};
inline E::E() = default; // compilation error here: would not initialize `i`
class F {
public:
F(); // promises to have a default constructor
private:
std::unique_ptr<int> p; // std::unique_ptr has a default constructor
};
inline F::F() = default; // works as expected
Suggest
first =default Instead of writing an equivalent implementation manually , Even if the implementation is just {}. Optionally , Omit from the initial declaration =default And provide a separate default implementation .
Note the default move operation . Objects from mobile still have to satisfy the invariants of their types , And the default implementation usually does not preserve the relationship between fields .
Outside the template , If =default No implementation provided , Use the =delete.
边栏推荐
猜你喜欢
随机推荐
Audio device strategy audio device output and input selection is based on 7.0 code
Use seven methods to enhance all the images in a folder
Functions and usage of imageswitch
How to implement safety practice in software development stage
[OKR target management] value analysis
Toast will display a simple prompt message on the program interface
In depth understanding of USB communication protocol
使用OneDNS完美解决办公网络优化问题
第3章业务功能开发(用户登录)
[re understand the communication model] the application of reactor mode in redis and Kafka
本周小贴士#136:无序容器
【深度学习】3分钟入门
面试官:页面很卡的原因分析及解决方案?【测试面试题分享】
Based on pytorch, we use CNN to classify our own data sets
[tpm2.0 principle and Application guide] Chapter 1-3
USB通信协议深入理解
js拉下帷幕js特效显示层
深入浅出图解CNN-卷积神经网络
Native JS verification code
青年时代历练和职业发展