C++初始化最佳实践

C++初始化最佳实践

引言

对于变量初始化,C++提供多种方式,较为复杂,在使用中很容易给开发者造成很大困惑;

C++11中的统一列表初始化(std::initializer_list)方式固然有很多优点,但是仍然有重载决议(若变量初始化使用大括号,则C++编译器优先调用统一列表初始化进行初始化)等令人迷惑的问题产生;

所以在开发过程中,开发者需要遵循一种实践规范来指导各种类型变量的初始化,以使得初始化语义明确,简明易懂;

原则

以下是我们认为理解容易、执行简单的一种初始化的最佳实践原则;当然,可能每一位开发者都有自己认为的最佳实践原则,只要简单易行即可,不必强求,故对于本原则,不喜勿喷;

本原则条目如下:

  • 须对所有变量进行初始化,即在使用前不能有未定义的值;
  • 使用语义明确且符合直觉的初始化方式;
  • 根据不同数据类型与给定初始化参数使用不同初始化方式;

最佳实践

综合上述三条原则,结合开发实践,总结了对于不同数据类型初始化的操作性较强的最佳实践,示例代码如下:

#include <string>
#include <vector>

using namespace std;

struct Stru {
    int a;
    string b;
};

class Demo {
public:
    Demo() = default;
    explicit Demo(const int a);
    explicit Demo(const int a, const double b);
    Demo(const Demo& rhs) = default;
    Demo& operator=(const Demo& rh) = default;
    ~Demo() = default;
private:
    int m_a;
    double m_b;
    std::vector<double> m_c;
};


int main()
{
    double a = 2.0;                         // 单个POD类型:拷贝初始化
    struct Stru c = {2, "stringTest"};     // 结构体:列表初始化   
    double b[3] = {1.0, 2.0, 3.0};         // 数组:列表初始化
    
    Demo demo1;                            // 单个类类型(无参数初始化):默认初始化
    Demo demo2(1, 2,5);                    // 单个类类型(参数化初始化):实参匹配直接初始化
    
    vector<double> vec = {1.0, 2.0, 3.0};  // 容器序列 : 列表初始化
    
    return 0;  
}

结论

对以上初始化最佳实践总结如下:

  • 单个POD类型数据的初始化: 拷贝初始化;
  • 单个类类型数据的无参数与参数化初始化: 默认初始化 or 实参匹配直接初始化;
  • 依次赋值各成员容器[结构体、数组、STL各种容器、可逐个赋值各成员的类、等]序列初始化: 列表初始化;
  • 其他方式尽量不要使用;

本文作者: 王同学