🔹 #pragma once 基础

  • 作用:防止头文件被多次包含(Multiple Inclusion),避免重复定义错误。
  • 使用场景:通常放在 头文件(.h/.hpp)开头
  • 语法
#pragma once


1. 与传统 include guard 对比

传统 include guard

#ifndef MYHEADER_H
#define MYHEADER_H

// 头文件内容

#endif // MYHEADER_H

使用 #pragma once

#pragma once

// 头文件内容

  • #pragma once 更简洁,不需要定义宏名
  • 编译器自动确保文件只被包含一次

2. 使用示例

假设有两个头文件 A.h 和 B.h

A.h

#pragma once
#include "B.h"

void funcA();

B.h

#pragma once

void funcB();

main.cpp

#include "A.h"
#include "B.h" // 即使这里再次包含 B.h,也不会重复编译

int main() {
    funcA();
    funcB();
    return 0;
}

✅ 编译器只会处理一次 B.h,避免重复定义。


3. 工作原理(原理简述)

  • 编译器在预处理阶段,记录已经处理过的文件路径
  • 如果同一文件再次被包含,则直接忽略
  • 比宏方式更高效,因为不需要预处理器多次展开宏检查

4. 优缺点

优点

  1. 简单明了,减少宏定义错误
  2. 避免宏命名冲突
  3. 编译速度通常比传统 include guard 更快(现代编译器)

缺点

  1. 非标准:不是 C/C++ 标准的一部分,但大多数现代编译器都支持(GCC、Clang、MSVC)
  2. 路径依赖:如果同一文件通过不同路径包含,可能失效
  3. 跨编译器兼容性:老旧编译器可能不支持

5. 注意事项

  1. 放在头文件最顶部,确保生效
  2. 不要与宏 include guard 冲突,可以同时使用(兼容老编译器):
#pragma once
#ifndef MYHEADER_H
#define MYHEADER_H

// 内容

#endif

  1. 尽量避免通过 不同相对/绝对路径重复包含同一文件

✅ 总结

特性#pragma onceinclude guard
写法简单,一行需要宏定义
可读性
编译效率高(现代编译器)略低
标准化非标准,但广泛支持标准 C/C++
跨路径重复包含可能有问题完全可靠

💡 小技巧:

  • 对新项目推荐 #pragma once,简洁高效
  • 对需要兼容老编译器的项目,可以 pragma + include guard 双保险