Cpp 初始化风格

cpp 的初始化风格

兼容 C 的初始化风格:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
int i = 10;
int a[] = {1, 2, 3};

struct Foo {
  char c;
  int i;
};

union Bar {
  char c;
  int i;
};

Foo foo = {.c = 'A', .i = 42};
Bar bar = {.c = 'A'};

但是 Cpp 引入了类, 这样会导致一个问题:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <iostream>

struct Foo {
};

struct Bar {
  Bar(const Foo& foo) {
    std::cout << "Bar::Bar" << std::endl;
  }
};

int main() {
  //Bar bar(Foo());     // 只是一个函数声明
  //Bar bar((Foo()));     // 解决方案 1
  Bar bar{Foo()};     // 解决方案 2
  
  return 0;
}

Cpp 的花括号初始化:

  • 好处是, 初始化更加安全。
  • 坏处是, 如果类型有 initializer_list 初始化方式, 则优先使用 std::initializer_list 构造函数。如果你想为一个类型添加 initializer_list 初始化方式, 你需要找到它的对象原来用花括号初始化改为用圆括号初始化。而且用户用花括号初始化时, 需要知道该类型有没有 initializer_list 的初始化方式。

for example:

1
2
3
vector<int> v{5};        // 使用 initializer_list 的方式初始化
vector<int> v = {5};     // 使用 initializer_list 的方式初始化
vector<int> v(5);

个人觉得 cpp 的花括号初始化和数组初始化有点混淆。如果不用兼容 C, 可以像 rust 一样使用 [] 初始化数组, {} 初始化结构体。但是 C 已经使用 {} 来初始化数组了, 如果 C++ 改用 [] 来初始化数组则不统一了。

= 的初始化风格

我更加喜欢类似于 rust, python, java 等语言的初始化方式, 使用 =:

1
2
3
4
5
6
7
int i = 10;         // 原始类型使用原来的风格。
auto mt = MyType(param1, param2);       // 非原始类型使用此风格。
                                        // 虽然不能声明多个同类型的对象, 但是不建议一行声明多个对象。See [ref](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es10-declare-one-name-only-per-declaration).
                                        // 不会有多余的操作, 因为有[复制消除](https://zh.cppreference.com/w/cpp/language/copy_elision)。
                                        // 同时它一定不是一个函数声明, 所以避免了函数声明和对象定义的混淆。

auto mt = MyType{param1, param2};       // 使用花括号初始化, 但是要注意不要混淆 initializer_list 的初始化方式, 且该类型以后最好不用添加 initializer_list 的初始化方式。

对于 C 的数据类型初始化风格:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int i = int();          // 使用 `=` 号赋值能保证内存会被初始化

// 指针类型
int* iptr1 = nullptr;   // 如果我想定义一个指针变量。
auto iptr2 = &i;

// cpp 的类型
Foo* foo_ptr1 = nullptr;
auto foo = Foo();
auto foo_ptr2 = &foo;

综上, 使用 = 初始化会保证变量会被初始化。这样会更加安全。所以优先使用 = 初始化, 如果变量不需要初始化时, 再使用非 = 的初始化风格, 是一个不错的选择。

References

0%