最近遇到了一个程序,一开始有些莫名其妙,最后经过思考、猜想、验证的过程,将其总结如下:
首先先上代码:
函数声明如下:
class Controller
{
using AnalysisManager = NST::analysis::AnalysisManager;
using FiltrationManager = NST::filtration::FiltrationManager;
class Running
{
public:
inline Running(Controller&);
Running() = delete;
Running(const Running&) = delete;
Running& operator=(const Running&) = delete;
inline ~Running();
private:
Controller& controller;
};
public:
Controller(const Parameters&);
Controller(const Controller&) = delete;
Controller& operator=(const Controller&) = delete;
~Controller();
int run();
private:
// initializer for global outptut
utils::Out::Global gout;
// initializer for global logger
utils::Log::Global glog;
// storage for exceptions
RunningStatus status;
// signal handler
SignalHandler signals;
// controller subsystems
std::unique_ptr<AnalysisManager> analysis;
std::unique_ptr<FiltrationManager> filtration;
};
只看其构造函数:
Controller::Controller(const Parameters& params) try
: gout {utils::Out::Level(params.verbose_level())}
, glog {params.log_path()}
, signals {status}
, analysis {}
, filtration {new FiltrationManager{status}}
{
// clang-format on
switch(params.running_mode())
{
case RunningMode::Profiling:
{
analysis.reset(new AnalysisManager{status, params});
if(analysis->isSilent())
utils::Out::Global::set_level(utils::Out::Level::Silent);
filtration->add_online_analysis(params, analysis->get_queue());
}
break;
case RunningMode::Dumping:
{
filtration->add_online_dumping(params);
}
break;
case RunningMode::Analysis:
{
analysis.reset(new AnalysisManager{status, params});
if(analysis->isSilent())
utils::Out::Global::set_level(utils::Out::Level::Silent);
filtration->add_offline_analysis(params.input_file(),
analysis->get_queue());
}
break;
case RunningMode::Draining:
{
filtration->add_offline_dumping(params);
}
break;
}
droproot(params.dropuser());
}
对于上述的构造函数,涉及到的几个知识点总结如下:
一:C++11特性初始化参数列表
C++11引入了一个新的初始化方式,称为初始化列表(List Initialize),具体的初始化方式如下:
int i = {1};
int j{3};
初始化列表在使用的时候有如下一些要求:
1. 当初始化内置基本类型的时候,列表初始化不允许出现隐式类型的转换,例如:
long double ld = 3.1415926536;
int a{ld}, b = {ld}; //出错,不允许出现精度的丢失
int c(ld), d = ld; // 非列表初始化,但是会出现精度的丢失
2. 初始化列表可以用于初始化结构体类型,例如:
#include <iostream>
struct Person
{
std::string name;
int age;
};
int main()
{
Person p = {"Frank", 25};
std::cout << p.name << " : " << p.age << std::endl;
}
3. 其他一些不方便初始化的地方使用,比如std<vector>的初始化,如果不使用这种方式,只能用构造函数来初始化,难以达到效果:
std::vector<int> ivec1(3, 5);
std::vector<int> ivec2 = {5, 5, 5};
std::vector<int> ivec3 = {1,2,3,4,5}; //不使用列表初始化用构造函数难以实现
二:初始化列表的作用
对于构造函数而言,初始化列表的作用无非是在对成员变量申请内存时进行初始化。执行构造函数时,先执行初始化表的内容,若初始化里面里面没有数据,侧编译器安装系统默认的方式对成员变量申请内存,进行系统默认的方式赋值,随后再进行构造函数中花括号内部的指令。
A.对于引用型成员变量和const常量型成员变量,则必须通过初始化表初始化该成员变量。 B.如果有类类型成员变量,而该类型又没有无参构造函数,则必须通过初始化表初始化该成员变量。 C.需要在子类中指定其基类部分的初始化方式,必须使用初始化表。 D.成员变量初始化顺序有声明顺序决定,而与初始化表的顺序无关。 E.对于参数列表中所列的成员变量,可以不包含所有的成员变量。
三:delete的作用
为了能够显式的禁用某个函数,C++11 标准引入了一个新特性:deleted 函数。程序员只需在函数声明后加上“=delete;”,就可将该函数禁用。类 X 的拷贝构造函数以及拷贝赋值操作符声明为 deleted 函数,就可以禁止类 X 对象之间的拷贝和赋值