web-dev-qa-db-ja.com

「ネームスペースの使用」汚染とは何ですか?

私はgoogleコーディングガイド [ここ] を見ていましたが、using namespaceまたはnamespace::functionの使用を推奨していません。

これはstdにも適用されますか? cout<<は、それなしでは機能しません。 この本 、同じことをお勧めします。では、cout<<またはusing namespace std;なしでstd::cout<<を使用するにはどうすればよいですか?

推奨される方法は何ですか? std::cout<<?ほとんどのC++教科書は、初心者にusing namespace std;を教えています。

15
Lord Loh.

Googleの標準を読んでいるので、_using namespace foo;_ディレクティブはどこでも使用できません。このディレクティブは、名前空間で宣言されたすべてのものを取り込み、衝突や予期しない動作の一般的な原因です。他の人は非常に一般的なものを引用しています:あなたはどこかにあなた自身の最大または最小メソッドがあり、それが誰かがあなたのメソッドにヘッダーを含んでいるsrcファイルで衝突し、そして_using namespace std;_と言う

特定の場所では、_using ::foo::bar;_の形式のusing宣言を使用できます

入力ディレクティブを使用するとコードの入力が大幅に削減されるため、人々はコードにディレクティブを使用することを好みますが、リスクが伴います。多くのcoutステートメントを含むファイルがある場合、std :: coutを100回入力する必要がないことは理解できますが、:: std :: coutを使用して簡単に言うことができます。私はこれらを変数宣言のように扱います。必要な場所にスコープを設定します。 10のファイル内の1つの関数が出力を書き込む必要がある場合は、最初にcoutの方法を宣言しないでください。実際の出力を実行している関数に入れてください。

_#include <ostream>
//using namespace std; // NO!
//using ::std::cout;   // less bad than using namespace, but I prefer to scope it

int main(int argc, char** argv)
{
   int rc = do_some_stuff(argc, argv);
   using ::std::endl;
   if (rc) { // print the success report
      using ::std::cout;
      cout << "The test run completed. The return code was " << rc << '.' << endl;
    } else {
      using ::std::cerr;
      cerr << "Unable to complete the test run." << endl;
    }
    return 0 == rc;
}
_

ほんの数行で出力を行うのは少し極端ですが、アイデアはわかります。

もう1つできることは、入力を最小限に抑えるためのエイリアスまたはtypedefです。 std :: whatはそれほど悪くはありませんが、数十のモジュールを含むソースの巨大なセットがあり、場合によってはconsole_gui::command_window::append("text")のようなコードを記述する必要があります。それはしばらくすると退屈になり、多くの長い行を引き起こします。私はすべてのようなもののために

_typedef console_gui::command_window cw;
cw::append("text");
_

エイリアスがローカルスコープで行われ、コードを読みやすくするために十分なコンテキストを保持している限り。

18
Michael Mathews

これは次の理由によります。1)名前の衝突を減らすために、ネームスペースの目的全体を無効にします。 2)usingディレクティブで指定された名前空間全体をグローバル名前空間で使用できるようにします。

たとえば、独自のmax()関数を含めて定義すると、std :: max()と衝突します。

http://en.cppreference.com/w/cpp/algorithm/max

Std :: member_you_wish_to_useを使用することをお勧めします。これは、使用する名前空間を明示的に指定するためです。

8
ApplePie

あなたが提供するリンクを引用する:

Using宣言は、.ccファイルのどこでも、.hファイルの関数、メソッド、またはクラスでも使用できます。

// .ccファイルでOK。

// .hファイルの関数、メソッド、またはクラスになければなりません。

:: foo :: bar;を使用

Googleスタイルでは、グローバルコンテキストでの名前空間のインポートの使用は禁止されていますが、ローカルネームスペースでは可能です。

宣言の使用がコードの限定された明確に見える部分にのみ影響を与えるあらゆる場所で、それは完全に許容されます。

グローバルコンテキストを汚染すると、無関係なコードが影響を受けます(ヘッダーを使用することにより)。ローカルコンテキストで実行しても何も起こりません。

6
Basilevs

質問にはすでに有用な回答がありますが、1つの詳細では不十分すぎるようです。

/のため、リファレンスを調べて学習しようとしても、ほとんどのプログラマは、最初はusingキーワードとnamespaceの使用法の説明に少し混乱しています。declarationdirective は、ある程度同等に読み取り、どちらもdで始まる比較的抽象的な長い単語です。

名前空間内の識別子には、名前空間に明示的に名前を付けることでアクセスできます。

myNamespace::myIdent

これは、入力するキーがはるかに多くなる場合があります。ただし、ほとんどの識別子に同じようにプレフィックスが付けられている場合は、コードの重要性が低下する可能性もあります。 usingキーワードは、これらのネームスペースのマイナス面を防ぐのに役立ちます。 usingはコンパイラレベル(マクロではない)で機能するため、その効果は使用されるスコープ全体に持続します。そのため、Googleスタイルでは、その使用を明確に定義されたスコープ(つまり、ヘッダーファイル内のクラスまたは関数)に制限していますcppファイル。

...もちろん、using宣言の間には違いがあります

using myNamespace::myIdent; // make myIdent an alias of myNamespace::myIdent

およびディレクティブを使用して

using myNamespace; // make all identifiers of myNamespace directly accessible

巨大なスコープで使用すると、後者はmuchの混乱を招きます。

1
Wolf

名前空間または名前空間:関数を使用することをお勧めしません-私がそれを誤解していない場合。

あなたがしました。非推奨はusing namespaceディレクティブにのみ適用されます(これは一般にabusing namespaceと呼ばれ、完全にユーモラスではありません)。関数またはオブジェクトの完全修飾名(std::coutなど)を使用することを強くお勧めします。

1
H2CO3

どうぞ:

#include <iostream>

int main()
{
    std::endl(std::operator<<(std::cout, "Hello world!"));
}

このように記述することで、エラーが発生しやすいADLを回避し、ディレクティブと宣言を使用します。

これは皮肉な答えになるはずです。 :-D

これについてはGoogleでHerb Sutterと一緒にいます。 C++コーディング標準から:

あなたはできるすべき宣言を使用して名前空間を使用するおよびディレクティブ #includeディレクティブの後の実装ファイルで自由に使用し、それについて気分が良い。反対の主張が繰り返されているにもかかわらず、宣言とディレクティブを使用した名前空間は悪ではなく、名前空間の目的を無効にすることはありません。むしろ、それらは名前空間を作成するものです使用可能

usingディレクティブを慎重に回避し、使用するすべてのものを明示的に指定することにより、このような天文学的にまれなイベントではおそらく決して発生せず、修正が困難ではない可能性のある名前空間の競合に取り掛かることができます(演算子)using宣言を使用するか、単にusing namespace stdを開始します。生産性の観点からは後者をお勧めします。

ほとんどのC++教科書は、初心者に名前空間stdの使用を教えています。彼らは貧弱なコーディング慣行を伝播していますか?

あなたが私に尋ねると、反対です、そして私は上記のサッターが同意すると思います。

現在、私のキャリアの中で、数千万のLOCにわたるコードベースでのusingディレクティブの直接の結果として、合計で約3つの名前空間の競合に遭遇しました。ただし、3つのケースすべてで、それらは50,000行を超えるレガシーコードにまたがるソースファイル内にあり、最初はCで記述され、その後C++に粗雑化し、12の異なるライブラリのヘッダーを含むさまざまな関数の膨大な折衷リストを実行し、ページにまたがる#includesの壮大なリスト。壮大な混乱にもかかわらず、ランタイムバグではなく、OSX(コードのビルドに失敗した1つのOS)でビルドエラーを引き起こしたため、修正はそれほど難しくありませんでした。この悪夢のような方法でコードを整理しないでください。問題はありません。

とは言っても、ヘッダーファイル内のbothusingディレクティブと宣言は避けてください。それはただの遅れです。しかし、ソースファイル、特に#includeディレクティブで満たされたページ全体を持たないファイルの場合、Googleで働いていないのであれば、気にしないでください。

1
user204677