C++/Cにおけるヘッダファイルの重複防止のための解決策と区別

1666 ワード

同じファイルがincludeで複数回行われることを避けるために、C/C++には2つの方式があり、1つは#ifndef方式、1つは#pragma once方式である.この2つの方式をサポートできるコンパイラでは、両者には大きな違いはありませんが、両者にはまだ細かい違いがあります.
     :
  #ifndef __SOMEFILE_H__
//   #if !define __SOMEFILE_H__ 
  #define __SOMEFILE_H__
  ... ... //   、    
  #endif
     :
  #pragma once
  ... ... //   、    

(一)#ifndefの方式はC/C++言語標準によってサポートされる
メリット:
(1)同一のファイルが複数回含まれないことを保証するだけでなく,完全に同一の内容の2つのファイル(またはコードフラグメント)が同時に含まれないことを保証することができる.
(2)C/C++言語標準のサポートを受け、コンパイラのいかなる制限を受けない
欠点:
(1)異なるヘッダファイルのマクロ名がうっかり「衝突」すると、ヘッダファイルが存在するのに、コンパイラが声明が見つからないと言い張る状況になる可能性があります.
(2)コンパイラはヘッダファイルを開くたびに重複定義があるか否かを判定する必要があるため、ifndefは大型プロジェクトをコンパイルする際にコンパイル時間が比較的長いため、pragma onceの方式をサポートし始めるコンパイラもある.
(二)#pragma onceは一般的にコンパイラによって保証される.
同じファイルは複数回含まれません.なお、ここでいう「同じファイル」とは、同じ内容の2つのファイルではなく、物理的に1つのファイルを指す.ヘッダファイルのコードの一部をpragma onceで宣言することはできませんが、ファイルのみに対して宣言できます.
メリット:
(1)マクロ名を考えるのに苦労する必要はありません.もちろん、マクロ名の衝突による奇妙な問題はありません.
(2)大規模なプロジェクトのコンパイル速度も向上した.
欠点:
(1)あるヘッダファイルに複数のコピーがある場合,本手法は重複して含まれないことを保証できない.もちろん、マクロ名の衝突による「宣言が見つからない」という問題に比べて、この重複は発見され、修正されやすい.
(2)pragma once方式は古いバージョンのコンパイラにサポートされていないが、サポートされているコンパイラの中には削除しようとしているものもあるので、互換性が悪い可能性がある.
 
(三)両者を一緒に置く方法も見られます.
  #pragma once
  #ifndef __SOMEFILE_H__
  #define __SOMEFILE_H__
  ... ... //   、    
  #endif

両者の長所を兼ね備えたいように見える.しかし、#ifndefを使用するとマクロ名が衝突する危険もあり、#pragma onceをサポートしないコンパイラのエラーも避けられないため、2つの方法を混用することはより多くのメリットをもたらすことはできないようで、慣れない人を困惑させることになります.
 
どちらの方式を選ぶかは、2つの方式を知る場合、具体的な状況によって異なります.欠点を避けるための合理的な約束さえあれば、どんな方法でも受け入れられると思います.
 
 
転載先:https://blog.51cto.com/10738651/1760066