読者です 読者をやめる 読者になる 読者になる

【C++】無名名前空間(unnamed namespace)

C++

無名名前空間とは何か

基本概念

無名名前空間(unnamed namespace)とは外部リンケージを持たない名前空間のこと。
これによってファイルスコープ内でのみ有効な局所的な変数や関数を宣言できる。

外部から読み取れない

無名名前空間内で宣言されたシンボルは一見グローバル空間に定義されているように見える。
しかし、実際には他のファイル・コンパイラからは実体を読み取れず、ローカルなものとなる。
これは、もし他のファイルで同名のシンボルがあったとしても、One Definition Ruleの侵害にあたらないこととなる。

A.cpp
namespace{
  int a = 0;
}

int b = 8;
B.cpp
#include "A.hpp"

int main(){
  extern int a; //ERROR
  extern int b;

  printf("%a, %b",a, b);
}

A.cppのint aは外部リンケージを持たないため外部結合できない。
int bは外部リンケージをもつ.

リンケージ (linkage)とは

ソースコードが複数ある場合にはリンケージという概念が登場します。関数およびグローバル変数が有する属性で、ファイルを越えて利用できるかどうかを示す性質です。実体が定義されたファイルの外で利用できる関数やグローバル変数を「外部 (external) リンケージをもつ」と表現します。逆に、実体が定義されたファイルの中でのみ利用できる関数やグローバル変数を「内部 (internal) リンケージをもつ」と表現します。

https://www.qoosky.io/techs/719b1e5927

例えば,グローバル変数は外部リンケージをもつ.
staticをつけると内部リンケージをもつようになる.
外部リンケージを持つ関数やグローバル変数を利用するためにはexternを使う.

名前衝突の回避

無名名前空間で宣言したシンボルも名前衝突の原因になることがある。
このときは::修飾子による名前解決が必要。

staticより優先的に使うべき

上記のように無名名前空間は,変数などに外部リンケージをもたせず,staticと同じ働きをする.
staticと比べて優先的に使うべきな理由として下記がある.

  1. namespaceは関数や変数だけでなく全てに対応できるため.
  2. staticは多くの使い方がありすぎる.

(参考)
http://stackoverflow.com/questions/4977252/why-unnamed-namespace-is-a-superior-alternative-to-static

パフォーマンスも向上することがある

名前空間付きのシンボルは外部リンケージを必要とせず、
コンパイラは、名前空間内で積極的に最適化することができる。

(参考)
http://stackoverflow.com/questions/357404/why-are-unnamed-namespaces-used-and-what-are-their-benefits