欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > C++小碗菜之一:尽量避免使用宏定义常量

C++小碗菜之一:尽量避免使用宏定义常量

2025/7/6 23:07:10 来源:https://blog.csdn.net/a1971191/article/details/144134229  浏览:    关键词:C++小碗菜之一:尽量避免使用宏定义常量

“在C++程序设计中,关于宏的第一规则就是:不要使用,除非不得不用。”

                                        ——《C++编程规范》

总阅读时间约为 7~12分钟。       

前言

C++语言从早期的C风格到现代C++,代码的可读性、安全性和性能得到了极大提升。然而,一些从C语言遗留下来的习惯,如大量使用宏定义常数,已经逐渐不再符合现代C++编程的最佳实践。

在这篇文章中,我们将探讨为什么应该尽量避免在C++中使用宏定义常数,并推荐采用更安全、更高效的替代方案——const。通过比较两者的优缺点以及实际应用场景,帮助我们编写更优雅、更稳定的代码。

什么是宏定义?

宏定义(Macro Definition) 是C和C++中预处理器的一种功能,用于定义符号常量、代码片段或函数样式的文本替换。在代码编译前,预处理器会将所有宏展开为对应的替换内容

常见宏定义的使用

1. 定义常量

宏可以用来定义符号常量:

#define PI 3.14159#define MAX_VALUE 100

在编译前,所有代码中出现的 PI 和 MAX_VALUE 都会被替换为相应的值。

2.定义代码片段

宏也可以用来定义一段代码片段:

#define PRINT_HELLO() printf("Hello, World!\n")

每次调用 PRINT_HELLO() 时,预处理器会将其替换为 printf("Hello, World!\n")。

3.定义带参数的宏

宏可以接受参数,就像函数一样:

#define SQUARE(x) ((x) * (x))

调用 SQUARE(5) 时,预处理器会将其替换为 ((5) * (5))。

4.避免重复包含的保护

头文件中通常会使用头文件保护,防止重复包含引发编译错误。

在往期博客【防止头文件被重复包含_*警告* 多重从属对象,句柄“1-CSDN博客】中有提到。

什么是const?

const 是C++ 中的一个重要关键字,用于声明一个变量、函数参数等为常量,防止其值在程序运行过程中被意外修改,如果尝试修改const变量,编译器会报错。

常见const的使用

1.定义普通常量

const int max_value = 100; //const对象必须初始化

max_value = 150;//错误,const 定义常量变量,该变量的值不可修改。

const常量必须在声明时进行初始化,这是因为const对象的值在创建后不能被修改,所以必须在创建时就赋予它一个值。

2.保护传参变量不可修改

const 限制变量的值在运行时不会被修改,防止意外的赋值操作。

void display(const std::string& message) {

    // message = "new text"; // 错误:无法修改 const 修饰的变量

    std::cout << message << std::endl;

}

以上为const最常见的用法,const不仅可以作用于变量,还可以作用于指针、引用、成员函数、成员变量等等……

为什么在C++中使用const替代宏定义常量?

1.类型不安全

宏只是简单替换,没有类型检查,可能导致隐藏的错误。而使用 const,编译器会进行类型检查,避免潜在的错误。

例子
#include <iostream>
// #define PI 3.14159
const double PI = 3.14159;
int main() {int radius = 5;int area = PI * radius * radius; // 没有类型检查,可能引发意外std::cout << "Area: " << area << std::endl;return 0;
}

这段代码并不会报错,也可以输出结果,这是因为C++ 允许从更高精度类型(如 double)向更低精度类型(如 int)进行隐式类型转换,但可能会导致精度丢失。在计算 PI * radius * radius 时:

  • PI 是 double,radius 是 int。
  • 计算 PI * radius 和 radius * radius 结果为 double。
  • 最终结果在赋值给 area 时被转换为 int,精度丢失(即小数部分被截断)。

2.作用域污染

宏常量的命名没有作用域保护,是全局的,一旦定义,所有代码都会受到影响。容易发生命名冲突。

例子:
#include <iostream>
// 在C++中,推荐使用const关键字来定义常量
// #define PI 3.14159 
// #define MAX 100
class MyClass1 {public:// 构造函数 初始化列表 初始化成员变量   MyClass1(const double PI, const int MAX) : PI(PI), MAX(MAX) {}void print() {std::cout << "MAXmyClass1: " << MAX << std::endl;std::cout << "PImyClass1: " << PI << std::endl;}private:const double PI;const int MAX;
};class MyClass {public: // 构造函数 初始化列表 初始化成员变量   MyClass(const double PI, const int MAX) : PI(PI), MAX(MAX) {}void print() {std::cout << "MAXmyClass: " << MAX << std::endl;std::cout << "PImyClass: " << PI << std::endl;}
private:const double PI;const int MAX;};
int main() {MyClass myClass(3.14, 10);MyClass1 myClass1(3.1415926, 10);myClass.print();myClass1.print();return 0;
}

注意:在 C++ 中,常量成员变量(const 成员)是不能在类的定义内部直接初始化的,必须通过构造函数的初始化列表进行初始化。

代码中并没有命名冲突,因为const 常量PI 和 MAX 都在不同的类中声明,它们各自独立,作用域被限定在类内。

结束语

随着语言的发展,const 已成为定义常量的推荐方式。为了编写更安全、稳定、易维护的代码,我们应当避免使用宏定义,转而使用 const,以适应现代C++的编程需求。

相关阅读

C++ 常量 | 菜鸟教程

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com