C ++の「using」宣言のスコープは何ですか?


100

C ++で「using」宣言を使用して、std :: stringとstd :: vectorをローカル名前空間に追加しています(不要な「std ::」の入力を節約するため)。

using std::string;
using std::vector;

class Foo { /*...*/ };

この宣言の範囲は何ですか?ヘッダーでこれを行うと、ヘッダーを含むすべてのcppファイルにこれらの「using」宣言が挿入されますか?


18
ここで他の回答から明確でない場合に備えて:- 宣言(またはディレクティブ)をインクルードファイル/ヘッダーのファイルスコープに配置しないでください。usingusingそれはヘッダーのユーザーにとって頭痛の種となるでしょう。
マイケルバー

実際には、入れていないusing宣言(ましてやディレクティブをヘッダに)すべてででも、名前空間の中に!これにより発生する問題については、ネームスペース内での宣言の使用の範囲を参照してください。
ニルスフォンバース

@NilsvonBarth:少し単純化しすぎています。usingクラスと関数のスコープで使用することは、議論された問題に関して安全です。
セバスチャンマッハ


ADL C ++ルックアップ 機能についてお読みください。
Alexis Wilke

回答:


59

C ++でヘッダーファイルを#includeすると、ヘッダーファイルの内容全体がソースファイルに含めた場所に配置されます。したがってusingusing宣言のあるファイルを含めると、ヘッダーファイルを含む各ファイルの先頭に宣言を配置するのとまったく同じ効果があります。


51
...これは一般的に悪いことです。
Catskul、2011

17
ただし、using宣言をa内に配置する場合namespace、その名前空間のスコープに制限されるため、通常は問題ありません(特定のニーズとスタイルに関する通常の注意事項を備えています)。
ゼロ

1
...ただし、名前空間の内部で使用する場合は、名前空間の外側で宣言されたクラスメソッドYを他の内部で囲むことができないなど、通常は悪い考えを回避しようとしていないことを確認してください。名前空間X。ローカルで名前空間Xを使用できるようにするためです。そのため、最初に名前空間::リゾルバーを使用しています。入力の問題がそれだけ大きい場合は、マクロ(コードの匂いが発生しやすい)またはそれ以上の場合は、それを独自のソース.cppに分離し、そこでのみ名前空間を使用します。
osirisgothra 2014年

1
これと同様の答えは良いアドバイスですが、質問には答えません。
Emile Cormier

116

using宣言を締め出すヘッダーファイルについて特別なことは何もありません。これは、コンパイルが始まる前の単純なテキスト置換です。

using宣言をスコープに制限できます。

void myFunction()
{
   using namespace std; // only applies to the function's scope
   vector<int> myVector;
}

12
関数内で使用できるとは思ってもみませんでした。
Agostino 2015年

1
すべての名前空間が1つの「コングロメレーター」タイプのファイルで使用されているので、各テストで特定の名前空間のものが使用されるため、gmockユニットテストは面倒で、すべての変数を修飾する必要があると思いました。using関数(またはgtest TESTマクロ!)の内部で使用すると、私の生活がとても良くなります!
dwanderson

54

usingステートメントのスコープは、コード内のどこにあるかによって異なります。

  • ファイルの上部に配置され、そのファイル全体にスコープがあります。
  • これがヘッダーファイルの場合、そのヘッダーを含むすべてのファイルにスコープが設定されます。一般的に、これは予期しない副作用を引き起こす可能性があるため、「良い考えではありません
  • それ以外の場合、usingステートメントは、それが発生した時点からブロックの終わりまでそれを含むブロック内にスコープを持っています。メソッド内に配置されている場合、そのメソッド内にスコープがあります。クラス定義内に配置されている場合、そのクラス内にスコープがあります。

5
usingクラススコープ内にステートメントを追加することは不可能だと思いました...?私はOPと同じ質問をstd::しました。それは、いたるところに入力するのを避けたかったからです。スマートポインターを備えた多くのベクトルを使用するクラスを取得し、5文字のstd::プレフィックスにより多くの行の長さが追加されます。それでusing、クラスを含む名前空間内のディレクティブが大丈夫かどうか疑問に思っていましたか?(ヘッダー内であっても)
thomthom '12 / 12/15

5
の範囲内に配置されている場合はnamespace { ... }どうですか?
einpoklum 2015年

だからあなたは完全に書くことができます:{名前空間blablaを使用して; クラス何とか{}; そして、その使用はクラスにのみ適用されますか?
Dinaiz 2016

8

スコープは、using宣言が含まれるスコープです。

これがグローバルスコープの場合、グローバルスコープになります。ヘッダーファイルのグローバルスコープにある場合、ヘッダーを含むすべてのソースファイルのグローバルスコープにあります。

したがって、一般的なアドバイスは、ヘッダーファイルのグローバルスコープで宣言を使用ないことです


3
それは十分に強くありません。「回避」を「
マーティンヨーク

1
回避しないほうが強いです。「他の車にぶつからないようにする」
ボボボボ2009

6

引用されたケースでは、ファイル(「翻訳単位」)、つまり、はい、それを含むすべてのファイル。

クラス内にusingステートメントを配置することもできます。その場合、それはそのクラスに対してのみ有効です。

一般に、ヘッダーで名前空間を指定する必要がある場合は、必要なすべての識別子を完全に修飾するのが最善の方法です。


usingクラスの宣言は、クラスの外部と同じように動作しないことに注意してください。たとえば、クラスのスコープに移動するcout代わりに、それを使用することはできませんstd::cout
ゼロ

2

それは正しいです。スコープは、using宣言を使用するモジュールです。モジュールに含まれるヘッダーファイルにusing宣言がある場合、それらの宣言のスコープはそのモジュールと、同じヘッダーを含む他のモジュールになります。


1

彼らが「しないでください」と言ったときにかなり修飾されていないコメントがいくつかあります。それは厳しすぎるが、それがいつ大丈夫かを理解する必要がある。

書くことusing std::stringは決してOKではありません。using ImplementationDetail::Foo独自のヘッダーに書き込む場合、そのヘッダーがImplementationDetail :: Fooを宣言すると、名前空間でusing宣言が発生した場合でも問題ありません。例えば

namespace MyNS {
    namespace ImplementationDetail {
        int Foo;
    }
    using ImplementationDetail::Foo;
}

1
ヘッダーのユーザーは次のように書くことができますMyNS::Foo
Peter Remmers

より良い例はusing boost::posix_time::ptimeです。確かにユーザーは書くことMyNS::ptimeができますが、それは世界の終わりではなく、などの機能を持つことができるという便利さによって相殺される可能性がありますMyFunction(ptime a, ptime b)
ゼロ

5
なぜあるusing std::string決してOK?自分の名前空間でも多くのstd::接頭辞を保存しますか?
thomthom 2013

@thomthom独自の名前空間などのスコープでラップした場合は問題ありません。
jcoffland 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.