C++ 中的宏定义和内联函数作用相似,本篇就来介绍这两个的使用以及不同。
# 宏定义
宏定义使用 define 关键字,有两种格式:宏名称以及名称 + 文本,后者还可以分为有参和无参。
# 宏名称
只有宏名称的一般用来标记头文件,为了防止编译时对相同的文件编译两遍,在第二次遇到相同的宏定义时就会跳过。
#ifndef HEADER_H | |
#define HEADER_H | |
#endif |
# 名称 + 文本
在编译时期就会将名称替换为对应的文本,下面第一个定义了一个变量,如果不进行初始化就访问则会报错。而 A 和 a 其实都是一个,都会被认为是 a,所以再次初始化变量 a 也会报错。
在定义有参数的宏时,注意要加上括号,因为在替换的时候是直接进行的文本替换,并不会考虑优先级等,否则结果就是错的。
#include <iostream> | |
#define A a | |
#define B 10 | |
#define C false | |
#define D 'a' | |
#define E "aaaa" | |
#define ADD(x, y) (x + y) | |
#define ADD_E(x, y) x + y | |
using namespace std; | |
int main() { | |
// cout << A << endl; error: Use of undeclared identifier 'a' | |
int A = 1; | |
// int a = 2; error: Redefinition of 'a' | |
cout << A << endl; // 1 | |
cout << a << endl; // 1 | |
cout << B << endl; // 10 | |
cout << C << endl; // 0 | |
cout << D << endl; // a | |
cout << E << endl; // aaaa | |
cout << ADD(1, 2) << endl; // 3 | |
cout << ADD_E(1, 2) * 3 << endl; // 7 | |
} |
# 特殊字符
# \
& #
& ##
\
是换行符。 #
符号将参数转换为加了双引号的值,所以 get_name () 输出是 "name"。 ##
将参数当做普通字符串与其他文本连接,所以成员变量分别为 age_ 和 name_,函数分别为 get_age () 和 get_name ()。
另外也看到有 #@
,不过我试了编译会报错: '#' is not followed by a macro parameter
。
#include <iostream> | |
#include <string> | |
#define CLASS(class_name, field_1, field_2) \ | |
class class_name { \ | |
private: \ | |
int field_1##_; \ | |
string field_2##_; \ | |
\ | |
public: \ | |
class_name(int field_1##_val) { \ | |
field_1##_ = field_1##_val; \ | |
field_2##_ = #field_2; \ | |
} \ | |
\ | |
~class_name() {} \ | |
\ | |
int get_##field_1() { \ | |
return field_1##_; \ | |
} \ | |
\ | |
string get_##field_2() { \ | |
return field_2##_; \ | |
} \ | |
}; | |
using namespace std; | |
CLASS(person, age, name) | |
int main() { | |
person* p = new person(10); | |
cout << p->get_age() << endl; // 10 | |
cout << p->get_name() << endl; // name | |
} |
# VA_ARGS
__VA_ARGS__
代表可变个数参数, ##__VA_ARGS__
代表参数个数可为 0。
#include <iostream> | |
#define sum(a, ...) add(a, __VA_ARGS__) | |
#define sum1(a, ...) add(a, ##__VA_ARGS__) | |
using namespace std; | |
int add(int a) { | |
return a; | |
} | |
int add(int a, int b) { | |
return a + b; | |
} | |
int add(int a, int b, int c) { | |
return a + b + c; | |
} | |
int main() { | |
// cout << sum(1) << endl; error: Expected expression | |
cout << sum(1, 2) << endl; // 3 | |
cout << sum(1, 2, 3) << endl; // 6 | |
// cout << sum(1, 2, 3, 4) << endl; error: No matching function for call to 'add' | |
cout << sum1(1) << endl; // 1 | |
cout << sum1(1, 2) << endl; // 3 | |
cout << sum1(1, 2, 3) << endl; // 6 | |
} |
# 内联函数
内联函数是在普通函数前面加上 inline
,会替换函数,这样就避免了运行时调用的开销。这种情况是定义与调用是分开的情况,当函数调用的开销不小于函数执行的开销时,适合使用内联函数。
#include <iostream> | |
inline void print() { | |
std::cout << "inline." << std::endl; | |
} |
#include <iostream> | |
#include "test1.cpp" | |
int main() { | |
print(); // inline | |
} |
# 不同
- 语义。define 只是进行文本替换,而 inline 则是定义函数。
- 类型检查。define 完全是傻瓜式替换,inline 会进行类型检查。
- 调试。inline 是可以调试的。