C++11 {} 初始化

  1. 简介

    • 说明

      • 主要内容是介绍{},即braces花括号在C++11中的作用。

    • 作用

      • 默认构造和默认初始化.
      • 值列表初始化。{}表示无参默认构造.
    • 默认值和随机

      #include <iostream>
      
      int main() {
                
                
         int a;
         int b{
                
                };
         std::cout << a << std::endl;
         std::cout << b << std::endl;
         return 0;
      }
      
      • 随机值和默认值.

      16
      0
      [Finished in 432ms]
      
    • 结构体

      #include <iostream>
      
      struct T {
                
                
         char a;
         char b;
         char c;
         char d;
      };
      
      int main() {
                
                
         T a;
         T b{
                
                };
         std::cout << std::hex << *(int*)&a << std::endl;
         std::cout << std::hex << *(int*)&b << std::endl;
         return 0;
      }
      
      • 输出都为0

      0
      0
      [Finished in 436ms]
      
      #include <iostream>
      
      typedef char (*T)[4];
      
      int main() {
                
                
         T a;
         T b{
                
                };
         std::cout << std::hex << *(int*)&a << std::endl;
         std::cout << std::hex << *(int*)&b << std::endl;
         return 0;
      }
      
      • 输出

      10
      0
      [Finished in 429ms]
      
      • 随机值和默认值0.

    • 重载

      #include <iostream>
      #include <vector>
      #include <initializer_list>
      
      struct T {
                
                
         T(){
                
                
             std::cout << "default" << std::endl;
         }
         T(std::initializer_list<int> initial) {
                
                
             std::cout << "initializer_list" << std::endl;
             std::vector<int> temp{
                
                initial};
         }
      };
      
      int main() {
                
                
         T a;
         T b{
                
                };
         T c{
                
                1,2,3};
         return 0;
      }
      
      • 输出

      default
      default
      initializer_list
      [Finished in 469ms]
      
    • 匹配规则

      • 优先匹配std::initializer_list构造,无参的({})才可以.

      • 无法构造initializer_list则参数拆分,匹配成员构造.

      • 对成员变量进行构造.

    • 成员变量构造

      #include <iostream>
      
      class T {
                
                
      public:
         char s[4];
      };
      
      int main() {
                
                
         T a{
                
                1,2,3,4};
         std::cout << std::hex << *(int*)&a << std::endl;
         return 0;
      }
      
      4030201
      [Finished in 432ms]
      
    • 数组和成员

      #include <iostream>
      
      class T {
                
                
      public:
         char a:4;
         char b:4;
         char s[3];
      };
      
      int main() {
                
                
         T a{
                
                1,2,3,4};
         T b{
                
                1,2,3,4,5};
         std::cout << std::hex << *(int*)&a << std::endl;
         std::cout << std::hex << *(int*)&b << std::endl;
         return 0;
      }
      
      40321
      5040321
      [Finished in 432ms]
      
  2. 初始化

    • 各种初始化

      int main() {
                
                
         int a(0);
         int b = 0;
         int c{
                
                 0 };
         int d = {
                
                 0 };
      }
      
      • 效果都一样,都是初始化变量.

    • 对等

      int main() {
                
                
         int b = {
                
                 0 };
         int c{
                
                 0 };
      }
      
      • 两种相等,后面介绍都统一用不包括=的.

  3. 赋值和初始化

    • 初始化和赋值

      #include <iostream>
      
      class T {
                
                
      public:
         T(char a) {
                
                 std::cout << "int" << std::endl; }
         explicit T(T*) {
                
                 std::cout << "float" << std::endl; }
         T(const T&) {
                
                 std::cout << "cons" << std::endl; }
         void operator=(const T&) {
                
                
             std::cout << "assign" << std::endl;
         }
      };
      
      int main() {
                
                
         T a = 1;
         //T b = nullptr;
         T c(nullptr);
         T d = a;
         d = a;
      }
      
      • 执行结果是

      int
      float
      cons
      assign
      
      D:\codes\vs\test\test\x64\Debug\test.exe (进程 9996)已退出,代码为 0。
      要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
      按任意键关闭此窗口. . .
      
      • 创建时隐式转换为对应的构造函数的入参.explicit,不允许隐式转换.

      • nullptr匹配了T*,注释掉的代码因为构造函数声明为explicit所以报错.

      • 两个T d=a也被隐式的转化为调用构造,而下面的是赋值,则调用赋值运算函数.

    • 小结

      • 声明时赋值是构造,其他则赋值.

  4. {}

    • 转换一下

      #include <iostream>
      
      class T {
                
                
      public:
         T(char a) {
                
                 std::cout << "int" << std::endl; }
         explicit T(T*) {
                
                 std::cout << "float" << std::endl; }
         T(const T&) {
                
                 std::cout << "cons" << std::endl; }
         void operator=(const T&) {
                
                
             std::cout << "assign" << std::endl;
         }
      };
      
      int main() {
                
                
         T a{
                
                 1 };
         T b{
                
                 nullptr };
         T c{
                
                (nullptr)};
         T d{
                
                 a };
         d = {
                
                 a };
         //d = { 1, a };
         d = (a);
         d = (1, a);
      }
      
      • 也是隐式转换,略有差异.

      int
      float
      float
      cons
      assign
      assign
      assign
      
      D:\codes\vs\test\test\x64\Debug\test.exe (进程 9400)已退出,代码为 0。
      要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
      按任意键关闭此窗口. .
      
      • 也会隐式转换.不容易出错.

  5. 出错

    • 函数还是构造

      int main() {
                
                
         int a();
         a = 2;
         return 0;
      }
      
      • 无参就是函数声明.

    • 窄化

      int main() {
                
                
         int a{
                
                1.0};
         return 0;
      }
      
      • 编译报错,因为会窄化,即double->int丢失数据.

    • 窄化概念

      • 基本类型之间,赋值导致了数据可能丢失.
    • 窄化二

      int main() {
                
                
         char a{
                
                1l};
         char b{
                
                127l};
         char c{
                
                128l};
         return 0;
      }
      
      • 这里前两个都不会,但是128超过了signed char的存储范围.

      • 上面的浮点不能往非浮点类型转换.

  6. 总结

    • 匹配优先级:initializer_list,构造,成员.

    • 作用: 统一初始化方式,适用性广.

    • 注意: 默认初始化的行为差异,auto的影响,空initializer_list:({}).

Guess you like

Origin blog.csdn.net/rubikchen/article/details/121888274