《Effective Modern C++》条款8:表示空指针优先选用nullptr,而非0或NULL

简述

  • 字面常量0的型别是int,而非指针。C++会在只能使用指针的语境中才勉强将其解释为空指针。

  • NULL是一个宏定义,而非指针。同样,C++会在只能使用指针的语境中才勉强将其解释为空指针。

    1
    2
    3
    4
    5
    6
    7
    8
    /* Define NULL pointer value */
    #ifndef NULL
    #ifdef __cplusplus
    #define NULL 0
    #else /* __cplusplus */
    #define NULL ((void *)0)
    #endif /* __cplusplus */
    #endif /* NULL */
  • nullptr是C++关键字,不具备整型型别。实际上,它也不具备指针型别,但是它可以隐式转换成任意指针型别,这也就是为什么nullptr可以用于初始化所有指针型别的原因。

Read more

《Effective Modern C++》条款10:优先选用enum class,而非enum

简述

众所周知,使用C++98中的枚举型别定义的枚举量,会泄漏到枚举型别所在的作用域中,这也意味着在此作用域内不能再有其他实体取相同的名称。因此,C++98中的枚举型别又称之为:不限作用域的枚举型别。

C++11为了解决这一问题,引入了限定作用域的枚举型别。由于限定作用域的枚举型别是通过”enum class“声明的,所以有时它们也被称为枚举类。

Read more

《Effective Modern C++》条款1:理解模板型别推导

简述

一个函数模板的声明和调用大致形如:

1
2
3
4
5
6
// 声明
template<typename T>
void f(ParamType param); // ParamType表示形参型别

// 调用
f(expr); // expr表示调用时传入的实参

模板型别推导的结果,不仅依赖于传入实参的型别,还依赖函数形参的型别。

Read more

整数求均值的几种方法

问题描述:

求均值最常用的方法是将两数相加再除以2,但是当两个数都大于其最大值的一半时,

相加的结果会发生内存移除。比如:

1
2
3
4
5
unsigned average(unsigned a, unsigned b)
{
return (a + b) / 2;
}
average(0x8000'0000 + 0x8000'0000) = 0; // 内存溢出
Read more

表达式:x=x&(x-1)的含义

表达式x = x & (x - 1)的含义是:

每执行一次,就会把x二进制格式下最右边的1变为0,换言之就是该表达式有效的执行次数等于x二进制格式下1的个数。

Read more

表达式:x & (-x)的含义

表达式:x & (-x)的含义:

返回x在二进制下的最右边的1表示的值:

  • 如果x是偶数,返回值能整除x且该值一定是2的n次幂,即能整除x的最大的2的n次幂
  • 如果x是奇数,返回值一定是1.
Read more

memset函数的使用陷阱

memset是C/C++编程中常用的函数,一般用于申请内存后的初始化操作,比如:

1
2
char* buffer = (char*)malloc(1024);
memset(buffer, 0x0, 1024);

memset接收三个参数:

  • 第一个参数是开始填充的地址
  • 第二个参数是填充的byte
  • 第三个参数要填充的字节数(注意是字节数)

这个函数看似简单,但是如果使用不当则会导致一些未知的bug。以下是目前遇到的几个陷阱。

Read more