const 注意事项

const 是类型修饰符, 通常用于修饰不可变变量 .

  • 用于定义常量. 如: const int num = 100; 定义常量一般也会使用#define 进行定义, 但使用 const 的好处是, 编译器会进行类型检查, 而使用#define 则不会.
  • 使用const修饰的默认为文件局部变量 , 即如果需要跨文件访问变量, 需要使用 extern 进行初始化修饰, 如: extern int num = 100; 才能从另外一个文件进行访问. 而没有使用 const 修饰的变量默认是 extern 的, 不需要显式的使用 extern 修饰.
  • const 常量必须初始化. 如:
  #include <iostream>

  class num {
      public:
          const int a = 100;

      public:
          void print() const;
  };

  void num::print() const {
      std::cout << "a: " << this->a << std::endl;
  }

  int main(void) {
      auto n = num{};
      std::cout << n.a << std::endl;
      n.print();
  }
  • const 与指针:
  const char *str = "hello";
  char *const str = "hello";

const* 左边时, 不能通过 *str = "world;" 进行赋值, 即 *str 是不可变的. 当 const*右边时, 不能通过 str = nullptr; 进行赋值, 即 str 是不可变得.

  • 可以将const 的指针赋值给 const 的指针; 反之不行.
  int num = 10;
  const int *const_num = &num;
  • 在函数参数中使用const, 可限制函数对参数的使用.
  void copy(char *dst, const char *src);

通过对src参数使用const修饰, 要求copy函数实现是不能通过src变量修改源字符串的内容, 否则编译器会报错.

  • 在类中初始化const成员.
  #include <iostream>

  class num {
      public:
          const int a;

      public:
          void print() const;
          num(int a);
  };

  num::num(int a): a(a) { }

  void num::print() const {
      std::cout << "a: " << this->a << std::endl;
  }

  int main(void) {
      auto n = num{100};
      std::cout << n.a << std::endl;
      n.print();
  }
  • 使用static修饰const变量时, 可以在类内/外部进行初始化.
  class num {
      public:
          static const int b;
          static const int c = 100;
  };

  const int num::b = 100;

上面是对 const 用法的一点总结, 发现有新的用法会持续补充. 如果觉得有帮助,可以扫描右边的微信打赏码支持一下.

class && struct && union 注意事项

class 作为C++中组织数据的基本类型. C++赋予 class 强大的组织能力, 可以包含数据成员方法. 使用 public, protected, private 进行访问控制;class 之间可以通过继承来复用代码; 通过 virtual 修饰函数和继承来实现多态. C++的面向对象功能离不开 class, 但C++为了兼容C代码, 还是保留了 struct 关键字. structclass 唯一的区别是: 成员访问控制. class 默认是 private, 而 struct 默认是 public. 下面看一个例子:

struct num_s {
    int m_a;

  private:
    int m_b;
};

class num_c {
    int m_b;

  public:
    int m_a;
};

上面的例子中, 通过structclass 分别定义了两个类, 它们的访问控制权限是一样的.

在C中还有一个和数据组织有关的关键字union, 那在C++中union又是怎样的呢?

  • union是为了节省内存设计的特殊类, 各个成员间共享同同一片内存.
  • 默认的访问控制权限是public.
  • 可以包含构造析构函数.
  • 不能包含引用成员, 不能包含虚函数, 不能继承与被继承.
  • 匿名union可通过外部直接访问.

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

bit field 注意事项

bit field位域的意思. 位域是类似于 sructunion 的自定义数据结构. 位域一般用于需要节省内存使用的场景(网络协议), 能够将结构体成员的范围限制在 bit 级别, 而不是基本类型:int, bool, char等级别.

需要注意以下几点:

  • 位域的内存布局与平台相关, 移植可能存在问题.
  • 位域的类型必须是整型或枚举类型, 带符号类型是未定义的.
  • 位域不能进行寻址.
  • 位域成员不能跨越两个类型.

下面直接看一个例子:

#include <iostream>

struct bitfield {
    unsigned short m_a : 1, m_b : 2, m_c : 3, : 5, m_d : 5;
};

int main(void) {
    bitfield bf = {
        .m_a = 1,
        .m_b = 1,
        .m_c = 1,
        .m_d = 1,
    };

    std::cout << sizeof(bitfield) << std::endl; // 输出:2
}

上面定义了 m_a...m_d 四个成员, 和一个匿名成员作为占位符. 如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

assert 注意事项

assert 即断言. 它是 , 而非函数. assert 一般用于:

  • 单元测试.
  • 程序初始化过程中, 状态判断.
  • 程序逻辑上不可能发生的事情, “以防万一” 的检查.

断言失败的默认后果是关闭程序, 所以注意断言错误处理不要和普通错误处理混淆. 断言的使用场景很有限, 良好的错误处理才能使程序健壮运行. 下面看一个例子:

#define NDEBUG
#include <cassert>

int main(void) {
    assert(1 != 1);
}

上面使用#define NDEBUG 宏关闭断言, 程序编译运行都正常. 如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

如何购买比特币

随着比特币出圈, 数字货币渐渐走入人们的视野. 我们经常能从不同的媒体上看到, xxx炒比特币赚了几百万. 一些好奇的小伙伴可能想尝尝炒数字货币的滋味. 下面写一个简单的入门教程, 希望能帮到有需要的小伙伴. 如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

购买比特币的第一步是找到一个靠谱的数字货币交易平台. 目前比较大数字货币交易平台有OKEx, Coinbase, Bitfinex这三家. 下面以OKEx为例进行说明. 可以点击邀请链接进行注册.

第一步: 选择语言和法币类型

第二步: 法币购入数字货币

第三步: 进行数字货币模拟交易

第四步: 进行数字货币交易

第五步: 数字货币兑换法币

完成以上五步, 则走完了购买数字货币的一个完整流程. 需要注意的是:
1) 对于数字货币交易国家并不持支持态度.
2) 进行数字货币兑换法币时, 注意不要有”购买比特币”的交易留言, 否则可能银行卡被冻结的风险.
3) 交易时, 最好使用不常用的银行卡, 避免被冻结后影响生活.
4) 银行卡单日交易交易额过高可能被东卡.
5) 数字货币兑换法币时, 最好选择平台认证的用户进行交易, 降低安全风险.
6) 被JC查水表时, 别慌, 配合JC办案即可.