最近学习C和C++时遇到了一个问题,那就是C++如何兼容C风格struct的初始化,因此查阅资料并总结一下。
根据查阅cppreference的结果,总结如下

C++的初始化可分为

  • 默认初始化

    int i;
    ClassType a;
    new int;
  • 值初始化

    ClassType();
    ClassType{};
    ClassType a{};
  • 直接初始化

    ClassType a(args);
  • 复制初始化

    ClassType a=ClassType(args);
    ClassType a=b;
  • 列表初始化

    ClassType a={val1, val2};
    ClassType a{val1, val2};
    ClassType{val1, val2};
  • 聚合初始化

    int a[5]={0};
    StructType a={.data=val1, .next=nullptr};
    StructType a={val1, nullptr};
    StructType a{val1, nullptr};
  • 引用初始化

    int& b=a;

注意:ClassType a();是新手容易犯的初始化错误,这实际上并不是初始化,而是声明函数。

默认初始化与值初始化对比

默认初始化创建的是具名对象,值初始化创建匿名对象

值初始化会进行内置类型的初始化,例如int初始化为0。

doSomething(int()); //此时int()的值为0

而默认初始化往往不会对内置类型进行初始化

int array[5]; //array中的值是不确定的

对于类来说都是调用默认构造函数

列表初始化与聚合初始化对比

由于C++中的struct与class实际的实现是一样的,为了兼容C语言中struct的初始化(聚合初始化),使用聚合初始化的类型有以下规定

  • 数组类型

    int array[]{1,2,3,4};
  • 所有非静态变量都为public,无用户编写的构造函数,无虚成员函数的类

    class TreeNode {
    public:
        int data;
        TreeNode* left;
        TreeNode* right;
    };
    
    TreeNode node{1, nullptr, nullptr}; //聚合初始化
    TreeNode node{ .data={1}, .left{nullptr}, .right=nullptr}; //聚合初始化

列表初始化要求类具有相应构造函数

  1. 若类具有std::initializer_list作为唯一参数,或者第一个参数为std::initializer_list,其他参数有默认值的构造函数,则试图匹配参数
  2. 如果前一个步骤无法完成,则试图与构造函数的参数进行匹配
std::vector<int> a{1,2}; /*列表初始化,调用
std::vector<T,Allocator>::vector(
        std::initializer_list<T> init,
        const Allocator& alloc = Allocator());*/
std::vector<int> b{a}; /*列表初始化,调用
std::vector<T,Allocator>::vector(
        const vector& other);*/

嘿嘿哟哟
17 声望4 粉丝