Effective C++ 笔记(2):尽量以const,enum,inline替换#define

简介: 条款二(clause 2) 尽量使用const,enum,inline替换#define(以编译器替换预处理器)1、使用const替换#define通常替换#define NUM 3.

条款二(clause 2)

尽量使用const,enum,inline替换#define(以编译器替换预处理器)

1、使用const替换#define

通常替换

#define NUM 3.14

const double Num = 3.14;//大写名称用于宏,这里改变写法

其中有两种特殊情况:
1、定义常量指针(往往放在头文件中)两种写法:

const char* const authorName = "Scott Meyers";
const std::string authorName("Scott Meyers");

保证指针指向和指针指向的变量不会变。
2、class专属常量:为了让常量的作用域限制于class,通常采取这样的方式:

class GamePlayer{
private:
    static const int Numbers = 5;
    int scores[Numbers];
};

上述代码在C++中编译通过,但是我们通常说Class定义在头文件中,因此class中的成员“定义”通常称之为声明,这与标准定义是不相同的,如果想取某个class专属常量的地址,或者编译器不通过(非要你定义这个成员才行),这样你需要在实现文件中定义:

const int Gameplayer::Numbers;

但在我的编译器中加上这句会导致编译错误,因为编译器要求const常量在定义时必须规定好数值。
当然,无法利用#define创建class专属常量,因为#define不重视作用域。
如果你的编译器比较旧不支持上述的语法则这样写:

class CostEstimate{
private:
    static const double Factor;
};

const double CostEstimate::Factor = 1.35;

2、或者用enum hack

class GamePlayer{
private:
//    static const int Numbers = 5;
    enum {Numbers = 5};
    int scores[Numbers];
};

也可以编译通过。
取const得地址是合法的,取enum和#define的地址通常不合法,如果不想别人通过指针或者引用获取你的某个整数的地址,那么enum可以实现你的想法。另外enum和#define一样不会导致非必要的内存分配。

3、不用宏实现函数

别用这种函数

#define CALL_WITH_MAX(a, b) F((a) > (b) ? (a): (b))

使用

template <typename T>
inline void callWithMax(const T& a,const T& b)
{
    f(a > b ? a : b); //f为简单比较函数
}

这种写法有很多好处,它遵守作用域和访问规则。

虽然我们对预处理器的要求变低了,但#define和#include依然是必需品。

目录
相关文章
|
18天前
|
存储 安全 编译器
第二问:C++中const用法详解
`const` 是 C++ 中用于定义常量的关键字,主要作用是防止值被修改。它可以修饰变量、指针、函数参数、返回值、类成员等,确保数据的不可变性。`const` 的常见用法包括:
63 0
|
7月前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
|
5月前
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
34 1
|
5月前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
75 0
|
6月前
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
259 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
7月前
|
编译器 C++
【C++】类和对象④(类的默认成员函数:取地址及const取地址重载 )
本文探讨了C++中类的成员函数,特别是取地址及const取地址操作符重载,通常无需重载,但展示了如何自定义以适应特定需求。接着讨论了构造函数的重要性,尤其是使用初始化列表来高效地初始化类的成员,包括对象成员、引用和const成员。初始化列表确保在对象创建时正确赋值,并遵循特定的执行顺序。
|
7月前
|
存储 安全 API
C++一分钟之-C++中的枚举类型(enum class)
【6月更文挑战第25天】C++的`enum class`(强类型枚举)在C++11中引入,增强了枚举的作用域和类型安全,减少命名冲突。它要求使用全名(如`Color::Green`)访问枚举成员,并能显式指定底层类型。常见问题包括默认值非0、隐式转换和范围溢出,解决办法是明确赋值、显式转换和选择合适底层类型。高效技巧包括用于状态机、作为函数参数、创建别名和迭代。掌握这些能提升代码质量。
231 0
|
7月前
|
编译器 C++
【C++】:const成员,取地址及const取地址操作符重载
【C++】:const成员,取地址及const取地址操作符重载
53 0
|
7月前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第二章 构造/析构/赋值运算 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第二章 构造/析构/赋值运算 笔记
|
2月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
62 2