7

私は少し疑問に思っていますnamespace。C using++では基本的に違いを知り、それを最良の方法で使用する方法を理解したいと思います。

私が見ているように、クラス名を解決するには(少なくとも)3つの方法があり、それらの中から選択する方法がわかりません。

  1. using namespace <namespace>
  2. using <namespace>::<what_to_use>
  3. <namespace>::<what_to_use> <use_it>

特に、パフォーマンスが何らかの形で関係している場合、それが単に構文的で好みの問題である場合、またはこれに関して私が考慮していない他のことがある場合の利点を知りたいと思います。

4

5 に答える 5

6

1つは、using名前空間ディレクティブです。これは、必要かどうかに関係なく、現在の名前空間内の指定された名前空間からすべてのシンボル名を取得します。確かに望ましくない。

2つ目は、名前空間宣言を使用することです。現在の名前空間に指定されたシンボル名のみが表示されます。利点は、毎回完全修飾名を入力する必要がないことです。

3番目は、シンボルの完全修飾名です。欠点は、記号を使用するすべての場所で完全修飾名を入力する必要があることです。

明らかに、2番目と3番目がより適切なものです。どちらにもパフォーマンスの違いはありません。唯一の違いは、入力する文字数です。コーディング標準で指定されている内容に応じて、どちらかを選択するだけです。

編集:
@Jerryが指摘しているように、宣言をADL(引数依存のルックアップ)と組み合わせて使用​​すると、望ましくない影響が生じる可能性があります。
あなたは私の答えの1つで詳細な説明を見つけることができます:

Koenigルックアップが名前空間でどのように機能するか、そしてなぜそれが良いことなのかについての詳細な説明?

セクションの下で、
なぜケーニッヒアルゴリズムの批判?

于 2013-01-03T10:13:05.233 に答える
4

使用するフォームが実際に違いを生む可能性がある (確かに、やや珍しい) 状況が 1 つあります。使用したいフォーム using namespace fooであり、最も一般的にはstd名前空間 (つまり、 を記述する場所) に適用されますusing namespace std;

最も明白な例は、ユーザー定義型の並べ替えを作成していることです。これは、ユーザーが独自に定義した型にも適用される可能性swapがあります。

スワップが定義されている場合はスワップを使用したいが、定義されていない場合は std::swap を使用したいという状況に陥っています。std::swapコードで直接使用するとstd::swap、型に独自のスワップが定義されていても、使用することになります。逆に、特に型にスワップを直接指定し、何も指定していない場合、コードはコンパイルに失敗します。

これを回避するには、次のようにします。

using namespace std;

template <class Iter>
void my_sort(Iter first, Iter last) {
    // ...
    if (*last < *first)
        swap(*first, *last);
}

これは、比較対象の型 (つまり、swapその型と同じ名前空間で定義された ) に固有のスワップを見つけ、存在する場合は (引数依存のルックアップを介して) std::swap、その型に何も定義されていない場合は ( を介してusing namespace std;) 見つけます。

これはパフォーマンスに影響を与える可能性があります。そのタイプ専用のスワップを記述している場合、一般的には、そうすることでパフォーマンスが向上することが期待できます。つまり、明示的に指定するとstd::swap機能する可能性がありますが、パフォーマンスが低下する可能性があります。

std::swapそれ以外の場合は、ほぼ完全に利便性と読みやすさの問題です --上記のような状況 (コードを書いている時点で) 少なくとも 2 つの可能性のいずれかの場合を除いて、私はほとんどフルネーム (例: ) を付けることを好みます。適切なものを選択する十分な余裕をコンパイラに与えたいと思います。

宣言/ディレクティブの使用が役立つと思うもう 1 つのケースは、名前空間が非常に深くネストされている場合です。Boost (わかりやすい例の 1 つ) には、毎回完全修飾名を使用すると便利に使用するには長すぎる名前がいくつかあります。これは、(現在、ありがたいことに、ほとんど廃止された)Boost Lambda ライブラリに特に当てはまりました。ここでは、のようなプレースホルダーを使用_1していましたが、最終的には次のようになりましたboost::lambda::placeholders::_1(ただし、メモリから行っているため、少なくとも部分的に間違っている可能性があります)。完全修飾名を使用することを主張しました。それはそもそもラムダライブラリを使用する目的の大部分を無効にしていたでしょう.

于 2013-01-03T10:29:08.753 に答える
2

パフォーマンスの向上やペナルティはまったくありません。すべての呼び出しと変数はコンパイル時に解決されます。

3 つの中から選択するのは、やや主観的なものです。はい、using namespace <ns>;グローバル名前空間を汚染することで眉をひそめることもあります、小さなファイルには安全に使用できると思います。

競合が予想されるテスト目的で 2 番目のものを使用する傾向がありますが、後で削除するだけです。修飾名と非修飾名の両方の組み合わせになる可能性があるため、これはさらに厄介になる可能性があります。

vector<std::string> x;

using std::vector;上部には がありますが、はありませんusing std::string;

私は3番目が好きです。

于 2013-01-03T10:15:32.653 に答える
1

コードのパフォーマンスへの影響はありません。これは純粋にコンパイル時の問題です。それは(理論的には)コンパイル時間にいくらかの影響を与えるかもしれませんが、それが測定可能な比率に達することはないと思います。

using namespace std(またはその他の名前空間)ヘッダーファイルでは絶対に避けてください。ヘッダーファイルはどこにでもインクルードでき、シンボルを挿入するとあいまいになる可能性があります。

一般に、名前空間は名前の衝突を避け、using namespaceこの目的を破壊するために存在します。using the_namespace::some_id程度は低いですが、そうです。あなたの質問に対する明確な答えはありませんが、私は一般的にこれらの規則に従います:

  1. using namespaceヘッダーファイルには入れないでください。
  2. 膨大な量のタイピングを節約できる場合を除いて、using namespaceとは避けてください。using必要に応じて名前空間エイリアスを使用します(つまり、namespace abbrv = some_really::long_and::nested_namespace;)。
  3. スコープを制限してみてくださいusing:これを関数とブロック、および名前空間スコープに入れることができます。つまり、.cppファイルにログ関数がある場合は、ファイルスコープではなく関数本体にusing std::cout;and (または使用しているもの)を配置します。using std::endl;
于 2013-01-03T10:18:34.587 に答える
0

主な理由は、(コンパイラーと人間のリーダーの両方にとって) あいまいさにつながる可能性があり、コンパイル自体が遅くなる可能性があることです (しかし、それは最初のことほど大きな問題ではありません)。

于 2013-01-03T10:14:27.373 に答える