私はコードでusing namespace std
を書くのは間違っていると、そして代わりにstd::cout
とstd::cin
を直接使うべきだと他の人に言われました。
なぜusing namespace std
は悪い習慣と考えられているのですか?それは非効率的ですか、それともあいまいな変数(std
名前空間の関数と同じ名前を共有する変数)を宣言する危険がありますか?パフォーマンスに影響しますか?
これはパフォーマンスとはまったく関係ありません。しかし、これを考慮してください:あなたはFooとBarと呼ばれる2つのライブラリを使用しています:
using namespace foo;
using namespace bar;
FooからBlah()
を、BarからQuux()
を問題なく呼び出すことができます。しかしある日、あなたは新しいバージョンのFoo 2.0にアップグレードしました。それは現在Quux()
と呼ばれる機能を提供します。 Foo 2.0とBarの両方がQuux()
をあなたのグローバル名前空間にインポートします。これは、特に関数のパラメータが一致した場合に、修正するためにある程度の努力を払うことになります。
foo::Blah()
とbar::Quux()
を使ったことがあれば、foo::Quux()
の導入は当然のことです。
私はすべてに同意します Gregが書いた しかし、私は付け加えたいと思います:Gregが言ったよりもさらに悪化する可能性があります!
Library Foo 2.0は関数Quux()
を導入することができました。それはあなたのコードが何年間も呼んだQuux()
よりもbar::Quux()
へのいくつかの呼び出しのための明白により良いマッチです。それならあなたのコードはまだコンパイルされます、しかしそれは黙って間違った関数を呼び出しますそして神は何を知っていますか。それは物事が得ることができるのと同じくらい悪いです。
std
名前空間にはたくさんの識別子があり、その多くはvery一般的なもの(list
、sort
、string
、iterator
など)であり、他のコードにも含まれる可能性が非常に高いことに注意してください。
これがありそうもないと思うなら:(質問される) - ここに私がこの答えを与えた約半年後にほぼ正確にこれが起こった(間違った関数が省略されたstd::
接頭辞で)あった 質問 。 ここ はそのような質問のもう一つの、より最近の例です。だからこれは本当の問題です。
もう1つデータがあります。何年も前に、標準ライブラリのすべての文字列にstd::
を付ける必要があるのも面倒なことです。それから私は、using
ディレクティブと宣言の両方が関数スコープを除いて禁止されることが始めに決められたプロジェクトで働いていました。何だと思う?接頭辞を書くのに慣れるまでに私たちのほとんどが非常に数週間かかった、そしてさらに数週間後に私たちのほとんどはそれが実際にコードを作ることに同意しさえしたもっと読みやすい。それには理由があります:あなたがより短い散文が好きかどうかは主観的ですが、接頭辞は客観的にコードを明確にします。コンパイラだけでなくあなたもそれを見つけますどの識別子が参照されているかがわかりやすくなります。
10年で、そのプロジェクトは数百万行のコードを持つようになりました。これらの議論は何度も繰り返されるので、私はかつて(許可された)関数スコープusing
が実際にプロジェクトで使用される頻度に興味を持っていました。私はそれについての情報源を手に入れ、そしてそれが使用されている場所を1〜2ダースしか見つけられなかった。私にとってこれは、一度試してみると、開発者がstd::
を使用することが許されている場所であっても100kLoCに1回でもディレクティブの使用を採用するのに十分なほど面倒ではないことを示しています。
結論:すべてのものに明示的に接頭辞を付けることは害を及ぼすことはなく、慣れるまでにほとんど時間がかからず、客観的な利点もあります。特に、それはコンパイラと人間の読者によるコードの解釈をより簡単にします - そしてそれはおそらくコードを書くときの主な目的であるべきです。
using namespace
をあなたのクラスのヘッダファイルに入れることの問題は、(あなたのヘッダファイルを含めることによって)あなたのクラスを使いたい人は誰でもそれらの他の名前空間を「使う」(すなわちすべてを見る)ことを強いるということです。
しかし、あなたはあなたの(私用)* .cppファイルにusingステートメントを自由に置くことができるかもしれません。
Cppファイルのusingステートメントは、ヘッダーよりもより良いですが(ヘッダーファイルを含むユーザーには影響がないため) (コードによっては、クラスの実装を維持することがより困難になる可能性があるため)、彼らはまだgoodではないと考えています。 これFAQトピック 言う、
Usingディレクティブは、従来のC++コードと名前空間への移行を容易にするために存在しますが、少なくとも新しいC++コードでは、通常は使用しないでください。
FAQは2つの選択肢を示唆しています。
使用宣言:
using std::cout; // a using-declaration lets you use cout without qualification
cout << "Values:";
Std ::と入力するだけです。
std::cout << "Values:";
私は最近 Visual Studio 2010 に関する苦情に遭遇しました。ほとんどすべてのソースファイルに次の2行が含まれていることがわかりました。
using namespace std;
using namespace boost;
多くの Boost 機能がC++ 0x標準に採用され、Visual Studio 2010には多くのC++ 0x機能があるため、突然これらのプログラムはコンパイルされませんでした。
したがって、using namespace X;
を回避することは将来を保証する形式です。使用中のライブラリやヘッダーファイル、あるいはその両方への変更を確実にする方法は、プログラムを壊すことにはなりません。
ショートバージョン:ヘッダーファイルで宣言またはディレクティブを使用してグローバルを使用しないでください。実装ファイルでそれらを自由に使用してください。 Herb SutterとAndrei Alexandrescuがこの問題について C++コーディング規約 で強調しています。
概要
名前空間の使用は、あなたが他の人に影響を与えるのではなく、あなたの便宜のためです:#includeディレクティブの前にusing宣言またはusingディレクティブを書かないでください。
推論:ヘッダーファイルでは、名前空間レベルのディレクティブや宣言の使用を記述しないでください。代わりに、すべての名前を明示的に名前空間修飾します。 (2番目の規則は最初から順になっています。なぜなら、ヘッダーは他のヘッダー#includeがそれらの後に現れるかもしれないものを知ることができないからです)
討論
手短に言うと、#includeディレクティブの後に宣言とディレクティブを実装ファイル内で自由に使用して名前空間を使用することができ、またそうすべきです。 反対の主張が繰り返されているにもかかわらず、宣言やディレクティブを使った名前空間は悪ではなく、名前空間の目的を損なうものでもありません。むしろ、それらは名前空間を使用可能にするものです 。
特にヘッダのように、グローバルスコープでusingディレクティブを使うべきではありません。ただし、ヘッダーファイルでも適切な場合があります。
template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
using namespace std; //no problem since scope is limited
return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}
明示的な修飾(std::sin
、std::cos
...)よりも短く、ユーザー定義の浮動小数点型を扱うことができるので(引数依存ルックアップを介して)、これはより優れています。
グローバルに使用されるの場合に限り、「悪い」と見なされます。なぜなら
using namespace xyz
を使うと、読者は特定の識別子がどこから来たのかを知るのが難しくなります。using namespace std
について話しているだけなら、あなたがつかむものすべてに気付いていないかもしれません - そしてあなたが別の#include
を追加するか、または新しいC++リビジョンに移動するとき、気付かなかった名前衝突を得るかもしれません。先に行き、それをローカルで(ほとんど)自由に使ってください。もちろん、これはstd::
の繰り返しからあなたを防ぎます - そして繰り返しはまた悪いです。
C++ 03には、クラスのswap
関数を実装するための慣用句 - 定型コード - がありました。実際にはローカルのusing namespace std
- あるいは少なくともusing std::swap
を使うことが推奨されました。
class Thing {
int value_;
Child child_;
public:
// ...
friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
using namespace std; // make `std::swap` available
// swap all members
swap(a.value_, b.value_); // `std::stwap(int, int)`
swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}
これは次のような魔法を行います。
std::swap
にvalue_
、すなわちvoid std::swap(int, int)
を選択します。void swap(Child&, Child&)
が実装されている場合は、コンパイラがそれを選択します。void std::swap(Child&,Child&)
を使用して、これらを最善のものと交換しようとするでしょう。C++ 11では、このパターンを使用する必要はもうありません。 std::swap
の実装は、潜在的な過負荷を見つけてそれを選択するように変更されました。
経験豊富なプログラマーは、自分の問題を解決するものは何でも使用し、新しい問題を引き起こすものは何も避け、この正確な理由からヘッダーファイルレベルのusingディレクティブを避けます。
経験豊富なプログラマーは、ソースファイル内の名前の完全修飾を避けようとします。これに対するマイナーな理由は、より少ないコードで十分であるときにもっと多くのコードを書くことが優雅ではないということです - 正当な理由がない限り 。これの主な理由は、引数依存検索(ADL)をオフにしていることです。
これらは何ですか 正当な理由 ?プログラマが明示的にADLをオフにしたい場合や、曖昧さを解消したい場合があります。
したがって、以下は問題ありません。
もう一つの理由は驚きです。
cout << blah
の代わりにstd::cout << blah
が表示される場合
これはcout
ですか?普通のcout
ですか?それは特別なことですか?
私はそれがグローバルに使われるべきではないことに同意します、しかしnamespace
のようにローカルに使うのはそれほど悪ではありません。これは "The C++ Programming Language" /からの例です。
namespace My_lib {
using namespace His_lib; // everything from His_lib
using namespace Her_lib; // everything from Her_lib
using His_lib::String; // resolve potential clash in favor of His_lib
using Her_lib::Vector; // resolve potential clash in favor of Her_lib
}
この例では、それらの構成から生じる潜在的な名前の衝突とあいまいさを解決しました。
そこで明示的に宣言された名前(His_lib::String
のようなusing宣言によって宣言された名前を含む)は、usingディレクティブ(using namespace Her_lib
)によって別のスコープでアクセス可能にされた名前よりも優先されます。
私はそれも悪い習慣だと思います。どうして?たった一日、私は名前空間の機能はものを分割することだと思ったので、私はそれをだめにしてはいけません。しかし、私がよく 'cout'と 'cin'を使うのであれば、cppファイルの中にusing std::cout; using std::cin;
と書いてください(#include
と共に伝搬するのでヘッダーファイルの中には絶対に入れないでください)。私は誰もがcout
またはcin
にストリームを命名することはないと思います。 ;)
コードを見て、それが何をするのかを知ってうれしいです。 std::cout
が表示されている場合、それがcout
ライブラリのstd
ストリームであることを知っています。 cout
が表示される場合、わかりません。 couldはcout
ライブラリのstd
ストリームです。または、同じ関数内でint cout = 0;
10行高い可能性があります。または、そのファイル内のstatic
という名前のcout
変数。それは何でもかまいません。
今、100万行のコードベースを取得します。これは特に大きくはありません。バグを検索しています。つまり、この100万行の中に、本来の動作をしない1行があることを意味します。 cout << 1;
はcout
という名前のstatic int
を読み取り、それを1ビット左にシフトし、結果を破棄できます。バグを探して、それを確認する必要があります。 std::cout
を見るのが本当に本当に好きな方法がわかりますか?
あなたが教師であり、生計を立てるためにコードを書いたり維持したりする必要がなければ、それは本当に良いアイデアのように思えるこれらのことの一つです。 (1)コードが何をするのか知っているコードを見るのが大好きです。そして、(2)私はそれを書いている人がそれが何をするか知っていたと確信しています。
複雑さを管理することがすべてです。名前空間を使うことはあなたが望まないということで引っ張るでしょう、そしてそれ故デバッグすることをより難しくするかもしれません(私はおそらく言う)。あちらこちらでstd ::を使うのは読むのがより難しいです(より多くのテキストとそのすべて)。
コースのための馬 - あなたが最も得意とする方法であなたの複雑さを管理します。
同時に多数の名前空間を使用することは災害のレシピですが、私の考えではJUST名前空間std
と名前空間std
のみを使用することはそれほど大きな問題ではありません。
そのため、それらの関数を "int"や "class"のような予約名と見なすだけでいいのです。
人々はそれについてそれほど怒っているのをやめるべきです。あなたの先生はずっと元気でした。 1つの名前空間を使うだけです。それが、名前空間を最初に使用することの全体的なポイントです。同時に複数を使用することは想定されていません。それがあなた自身のものでない限り。そのため、再定義は行われません。
あなたは、あなたとは異なるスタイルやベストプラクティスの意見を持つ人々によって書かれたコードを読めるようにする必要があります。
あなたがcoutだけを使っているのであれば、だれも混乱することはありません。しかし、たくさんの名前空間が飛び交っていて、このクラスを見て、それが何をするのか正確にはわからないとき、名前空間を明示的に持つことは一種のコメントとして機能します。一目見ただけで、「ああ、これはファイルシステムの操作です」とか「ネットワーク関連のことをやっている」とか。
考えて
// myHeader.h
#include <sstream>
using namespace std;
// someoneElses.cpp/h
#include "myHeader.h"
class stringstream { // uh oh
};
これが単純な例であることに注意してください。もし20個のインクルードや他のインポートを含むファイルがあるなら、問題を解決するために通過するべきたくさんの依存関係があるでしょう。さらに悪いことに、競合する定義によっては他のモジュールで関連のないエラーが発生する可能性があるということです。
それはそれほど恐ろしいことではありませんが、ヘッダファイルやグローバル名前空間でそれを使わないことで頭痛の種を減らすことができます。非常に限られた範囲でやっても大丈夫ですが、私は自分の関数がどこから来ているのかを明確にするために余分な5文字をタイプすることに問題があったことはありません。
名前空間は名前付きスコープです。名前空間は、関連する宣言をグループ化したり、別々の項目を別々にしておくために使用されます。例えば、別々に開発された2つのライブラリーが異なる項目を参照するために同じ名前を使用することがありますが、ユーザーは両方を使用することができます。
namespace Mylib{
template<class T> class Stack{ /* ... */ };
/ / ...
}
namespace Yourlib{
class Stack{ /* ... */ };
/ / ...
}
void f(int max) {
Mylib: :Stack<int> s1(max) ; / / use my stack
Yourlib: :Stack s2(max) ; / / use your stack
/ / ...
}
名前空間名を繰り返すことは、読者と作家の両方にとって邪魔になる可能性があります。その結果、特定の名前空間からの名前が明示的な修飾なしで利用可能であると述べることは可能です。例えば:
void f(int max) {
using namespace Mylib; / / make names from Mylib accessible
Stack<int> s1(max) ; / / use my stack
Yourlib: :Stack s2(max) ; / / use your stack
/ / ...
}
名前空間は、さまざまなライブラリやさまざまなバージョンのコードを管理するための強力なツールを提供します。特に、それらは、非ローカル名への参照を明示的にする方法の代替案をプログラマに提供します。
ソース:Bjarne StroustrupによるC++プログラミング言語の概要
私はここで他の人たちと同意します、しかし読みやすさに関する懸念に対処したいです - あなたはあなたのファイル、関数またはクラス宣言の上で単にtypedefを使うことによってそれの全てを避けることができます。
クラス内のメソッドは類似のデータ型(メンバ)を扱う傾向があるので、クラス宣言で通常使用します。typedefは、クラスのコンテキスト内で意味のある名前を割り当てる機会です。これは実際にはクラスメソッドの定義の読みやすさを助けます。
//header
class File
{
typedef std::vector<std::string> Lines;
Lines ReadLines();
}
実装では:
//cpp
Lines File::ReadLines()
{
Lines lines;
//get them...
return lines;
}
とは対照的に:
//cpp
vector<string> File::ReadLines()
{
vector<string> lines;
//get them...
return lines;
}
または
//cpp
std::vector<std::string> File::ReadLines()
{
std::vector<std::string> lines;
//get them...
return lines;
}
懸念を明確にするための具体的な例。 fooとbarの2つのライブラリがあり、それぞれ独自の名前空間を持っている状況があるとします。
namespace foo {
void a(float) { /* does something */ }
}
namespace bar {
...
}
次のように、自分のプログラムでfooとbarを一緒に使用するとしましょう。
using namespace foo;
using namespace bar;
void main() {
a(42);
}
この時点で、すべて問題ありません。あなたがあなたのプログラムを実行するとき、それは「何かをします」。しかし、後でbarを更新し、それが次のように変更されたとしましょう。
namespace bar {
void a(float) { /* does something completely different */ }
}
この時点でコンパイラエラーが発生します。
using namespace foo;
using namespace bar;
void main() {
a(42); // error: call to 'a' is ambiguous, should be foo::a(42)
}
ですから、どの「a」を意味しているのかを明確にするために、何らかのメンテナンスを行う必要があります(つまりfoo::a
)。これはおそらく望ましくないことですが、幸いなことにそれは非常に簡単です(コンパイラがあいまいなものとしてマークするa
へのすべての呼び出しの前にfoo::
を追加するだけです)。
しかし、barが代わりに次のようになっているという別のシナリオを想像してください。
namespace bar {
void a(int) { /* does something completely different */ }
}
この時点で、a(42)
への呼び出しは突然、bar::a
ではなくfoo::a
にバインドされ、「何か」を行う代わりに「まったく異なる」ものになります。コンパイラによる警告などはありません。あなたのプログラムはただ静かに以前とは全く異なる何かをし始めます。
あなたが名前空間を使うとき、あなたはこのようなシナリオを危険にさらしています、それは人々が名前空間を使うことに不快である理由です。名前空間内のものが多ければ多いほど、競合のリスクが高くなるため、名前空間stdを使用することは他の名前空間よりもさらに不快になる可能性があります。
結局これは、書き込み性と信頼性/保守性の間のトレードオフです。読みやすさも考慮に入れるかもしれませんが、私はどちらにしてもそのための議論を見ることができました。通常、私は信頼性と保守容易性がより重要であると言いますが、この場合、かなりまれな信頼性/保守容易性への影響のために常に書き込みコストを支払うでしょう。 「最良の」トレードオフはあなたのプロジェクトとあなたの優先順位を決定します。
名前空間stdを使用するとcountのあいまいさが原因でコンパイルエラーが発生する例。これはアルゴリズムライブラリの関数でもあります。
#include <iostream>
using namespace std;
int count = 1;
int main() {
cout<<count<<endl;
}
私はそれがすべての状況下で必ずしも悪い習慣であるとは思わないが、あなたがそれを使うときあなたは注意する必要がある。あなたがライブラリを書いているなら、あなたはおそらくあなたのライブラリが他のライブラリと頭を突き合わせないように名前空間を持つスコープ解決演算子を使うべきです。アプリケーションレベルのコードでは、私はそれが悪いとは思わない。
ソフトウェアやプロジェクトのパフォーマンスを低下させることはありません。ソースコードの先頭に名前空間を含めることは悪くありません。 using namespace std
命令を含めることは、あなたのニーズとあなたがソフトウェアやプロジェクトを開発している方法によって異なります。
namespace std
はC++標準関数と変数を含みます。この名前空間は、C++の標準関数をよく使う場合に役立ちます。
これで述べられているように page :
名前空間stdを使ったステートメントは一般に悪い習慣と考えられています。このステートメントの代わりに、型を宣言するたびにスコープ演算子(::)を使用して識別子が属する名前空間を指定します。
そして この意見を見てください :
名前空間を多用し、何も衝突しないことを確実に知っている場合は、ソースファイルで「using namespace std」を使用しても問題ありません。
そのネームスペースからすべての関数と変数を呼び出すので、ソースファイルにusing namespace std
を含めるのは悪い習慣です。 namespace std
に含まれている他の関数と同じ名前で新しい関数を定義したい場合は、その関数をオーバーロードしてしまい、コンパイルや実行によって問題が発生する可能性があります。期待どおりにはコンパイルも実行もされません。
これで述べられているように page :
このステートメントは、std名前空間で定義されたクラスまたは型にアクセスするときはいつでもstd ::と入力する手間を省きますが、std名前空間全体をプログラムの現在の名前空間にインポートします。いくつかの例を挙げて、これがそれほど良いことではない理由を理解しましょう。
...
今、開発の後期段階で、「foo」というライブラリにカスタム実装された別のバージョンのcoutを使用したいと思います(たとえば)。
...
どのライブラリにcoutが指しているのか、あいまいさがあることに注意してください。コンパイラはこれを検出してプログラムをコンパイルしない可能性があります。最悪の場合、識別子がどの名前空間に属しているのか特定していないので、プログラムはコンパイルしても間違った関数を呼び出すかもしれません。
私は他人に同意します - それは名前の衝突、あいまいさを求めています、それから事実はそれがそれほど明白ではないということです。私はusing
の使用を見ることができますが、私の個人的な好みはそれを制限することです。私はまた他の何人かが指摘したことを強く考慮する。
かなり一般的な名前である可能性がある関数名を見つけたいが、それをstd
名前空間(またはその逆)だけで見つけたい場合は、名前空間std
、名前空間X
にないすべての呼び出しを変更します。それでは、どのようにこれを行うことを提案しますか?それを実行するプログラムを作成することもできますが、プロジェクトを維持するためのプログラムを作成するよりも、プロジェクト自体の作業に時間を費やすほうがよいでしょうか。
個人的に私は実際にはstd::
という接頭辞を気にしません。持っていないより見た目が好きです。それが明示的で、「これは私のコードではありません...私は標準ライブラリを使用しています」と言っているのか、それともそれが何か他のものであるのかどうかわかりません。私が最近C++に入ったばかりであることを考えると、これは奇妙かもしれません(C言語や他の言語をずっと以前から使用していますし、Cはアセンブリのすぐ上の私のお気に入りの言語です)。
他にも1つありますが、それは上記のことや他の人が指摘していることといくらか関係しています。これは悪い習慣かもしれませんが、私はstd::name
を標準ライブラリのバージョンとプログラム固有の実装のために予約することがあります。はい、確かにこれはあなたを悩ませ、あなたを激しく噛みつかせることができます、しかしそれはすべて私がこのプロジェクトを最初から始めたそしてそれのための唯一のプログラマーであることに帰着します。例:std::string
をオーバーロードしてstring
と呼びます。私は役に立つ追加があります。私はCとUnix(+ Linux)が小文字の名前になる傾向があったためにこれを行った。
それ以外に、名前空間のエイリアスを持つことができます。これは参考にされなかったかもしれないそれが有用であるところの例です。私はC++ 11標準、特にlibstdc ++を使います。まあ、それは完全なstd::regex
サポートを持っていません。確かにそれはコンパイルされます、しかしそれはプログラマーの側でエラーであることの線に沿って例外を投げます。しかし、それは実装の欠如です。それで、これが私がそれを解決した方法です。 Boostの正規表現をインストールしてリンクします。それから、libstdc ++が完全に実装されたときにこのブロックを削除するだけで、コードは変わらないように、次のようにします。
namespace std
{
using boost::regex;
using boost::regex_error;
using boost::regex_replace;
using boost::regex_search;
using boost::regex_match;
using boost::smatch;
namespace regex_constants = boost::regex_constants;
}
それが悪い考えかどうかについては議論しません。しかし、私はそれが私のプロジェクトのためにそれをきれいにしておくと同時にそれを具体的にしていると主張するつもりです:本当私はBoost BUTを使わなければなりません。はい、あなた自身のプロジェクトを始めて、最初から標準(...)で始めることは、メンテナンス、開発、そしてプロジェクトに関わる全てを手助けすることに非常に長い道のりを要します!
編集:
今、私は時間を持っています、ただ何かを明確にするために。 STLの中でクラスの名前を故意にそしてより具体的に代わりに使用することは実際には良い考えではありません。私は 'String'のアイデアが嫌いだったので、文字列は私にとって例外です(ここで最初、上、または2番目を無視します。現状では、私はまだCに非常に偏っていて、C++に偏っています。細部を控えて、私が取り組んでいるものの多くはCに適合します(しかし、それは良い練習であり、私自身を他の言語を学び、b。オブジェクト/クラスなどに偏らないようにするための良い方法でした。心が狭く、傲慢が少なく、より受け入れやすい。しかし、ISが便利なのは、すでにリストされているものです。実際にはlistを使います(それはかなり一般的です、そうではありませんか?)。 using namespace std;
を実行するには、そのために、私はそれが標準的な使用であることを意図しているなら、私はそれを指定しなければならないことを知っている、コントロールで、特定であるのを好む簡単に言うと:許可されているとは限りません。
そしてBoostの正規表現をstd
の一部にすることについて。私は将来の統合のためにそれをします - そして、これもバイアスです - 私はそれがboost::regex:: ...
ほど醜いとは思いません。確かにそれは私にとってもう一つのことです。 C++には、外観やメソッドでまだ完全に受け入れられていないものがまだたくさんあります(別の例:可変数テンプレートと可変長引数[可変数テンプレートは非常に便利ですが!])。私がそれを受け入れるものでさえもそれは困難であり、そして私はまだ彼らと問題を抱えている。
未修飾のインポートされた識別子では、識別子が宣言されている場所を見つけるために grep のような外部検索ツールが必要です。これはプログラムの正しさについての推論を難しくします。
これは悪い習慣で、しばしばグローバル名前空間汚染として知られています。複数の名前空間がシグネチャを持つ同じ関数名を持っている場合、問題が発生する可能性があります。その場合は、std::cout
のように名前空間を関数呼び出しで指定している場合は回避できます。お役に立てれば。 :)
場所によって異なります。それが一般的なヘッダである場合は、グローバル名前空間にマージすることで名前空間の値を減らしています。覚えておいて、これはモジュールグローバルを作るためのきちんとした方法であるかもしれません。
「名前空間stdを使うのはなぜですか。 C++で悪い習慣と考えられている?」
言い換えると、5文字の余分な文字を入力するのが面倒だと思われるのはなぜでしょうか。
考えてみてください。数値ソフトウェアを作成するとき、「ベクトル」が問題領域の最も重要な概念の1つである場合に、一般的な「std :: vector」を「vector」に切り捨ててグローバルネームスペースを汚染することを検討するのはなぜでしょうか。
あなたの質問に答えるために、私は実際にこのように見ています。多くのプログラマー(全員ではない)が名前空間stdを呼び出します。したがって、名前空間stdにあるものと同じ名前を付けたり使用したりすることは避けてください。これは大したことではありませんが、厳密に言えば可能性のある一貫性のある単語や仮名の数と比べてもそれほど多くありません。
つまり、「これが存在していることに頼らない」というのは、存在していないことに頼るように設定するだけです。あなたは常にコードスニペットを借用しそして絶えずそれらを修理している問題を抱えることになるでしょう。ユーザー定義のものや借用したものは限られた範囲に収めるべきであり、グローバルには非常に控えめにしてください(正直に言って、グローバルは「今すぐコンパイル、健全性を維持」の目的の最後の手段です)。 stdを使うのは "cout"と "std :: cout"の両方でうまくいくが、stdを使わないのは "std :: cout"でしかうまくいかないからです。あなた自身のコードをすべて書くのに十分幸運であるとは限らないでしょう。
注意:コンパイラがどのように動作するかについて実際に少し学ぶまで、効率の問題にあまり集中しないでください。コーディング経験が少ない場合は、優れたコードをどれほど単純なものに一般化できるかを理解する前に、それらについて詳しく学ぶ必要はありません。あなたがCで全部を書いたのと同じくらい簡単です。良いコードはそれが必要とするのと同じくらい複雑です。
私の経験から言うと、sayを使ったライブラリが複数ある場合はcout
ですが、違う目的のために間違ったcout
を使うことがあります。
たとえば、using namespace std;
(またはusing namespace otherlib;
)ではなく、std::cout
と'otherlib::cout'
を入力し、coutだけを入力した場合は、間違った方を使用してエラーが発生する可能性があります。 std::cout
を使用してください。
はい、名前空間は重要です。自分のプロジェクトに入った後は、1つのvar宣言をソースコードにインポートする必要がありましたが、コンパイル時に他のサードパーティライブラリと競合しました。
最後に、私は他の方法でそれを回避し、コードを明確にしなくてはなりませんでした。
local または global を使用するかどうかは、アプリケーションによって異なります。
その理由は、ライブラリをローカルで使用すると、コードが混乱することがあるためです。読みやすさが低下しています。
そのため、競合の可能性がある場合に限り、ローカルでライブラリを使用する必要があります。
私はもっと経験のある人ではありません。それで、私が間違っているかどうか私に知らせてください。
正直なところ、私にとっては、インデントのためのスペースの数について議論しているようなものです。ヘッダーにディレクティブを使用すると破損する可能性があります。しかし、C + +ファイルで?一度に2つの名前空間を使っているのであれば。しかし、あなたがそれを使うのであれば、それは本当の効率よりもスタイルについてのことです。字下げに関するスレッドがとても人気がある理由を知っていますか?誰もがそれについて何かを言うことができ、非常に賢くて経験豊富に聞こえます。
これは、using namespace std;
が名前の衝突問題を引き起こす可能性があることを示す例です。
この例では、非常に一般的なアルゴリズム名(std::count
)の名前が非常に妥当な変数名(count
)と衝突しています。
ケースバイケースです。私達はそれが寿命を超えてソフトウェアの「総所有コスト」を最小にしたいです。 「using namespace std」と記述するといくらかコストがかかりますが、notusingを使用すると読みやすさにコストがかかります。
人々がそれを使用するとき、stdライブラリが新しいシンボルと定義を導入するとき、あなたのコードはコンパイルをやめて、あなたが変数を改名することを強いられるかもしれないと正しく指摘します。それでも、これはおそらく長期的には良いことです。驚くべき目的でキーワードを使用していると、将来のメンテナが一時的に混乱したり、気が散ったりするためです。あなたは=と言うわけではありません。Vectorというテンプレートを作成したいのですが、これは他の誰もが知っているベクトルではありません。)このようにC++ライブラリに導入された新しい定義の数は十分に少ないのです。 is)この種の変更を行わなければならないコストは高くありませんが、他の目的でstdシンボル名を使用しないことによって得られる明確さによって相殺されます。
クラス、変数、関数の数を考えると、std ::と記述するとコードが50%膨れ上がり、頭を動かすのが難しくなります。 1画面分のコードに取り込まれる可能性があるメソッドのアルゴリズムまたはステップは、前後にスクロールする必要があります。これは実費です。多分それは高コストではないかもしれません、しかしそれを否定さえする人々は経験の浅い、独断的な、または単に間違っています。
私は以下のような規則を提案します。
stdは他のすべてのライブラリとは異なります。それは皆が基本的に知る必要がある1つの図書館です、そして、私の見解では言語の一部として最もよく考えられます。一般的に言って、using namespace std
には他のライブラリにはないとしても優れたケースがあります。
これをヘッダーに使用してコンパイル単位(.cppファイル)の作成者に決定を強制しないでください。 常に決定をコンパイル単位の作成者に延期する。using namespace std
を至る所で使用することを決定したプロジェクトであっても、その規則の例外として最もよく処理されるいくつかのモジュールでうまくいくかもしれません。
名前空間機能によって、同じ定義のシンボルを持つ多くのモジュールを持つことができますが、そうするのは混乱します。可能な限り名前を変えてください。名前空間機能を使用していなくても、fooという名前のクラスがあり、stdにfooという名前のクラスが導入されている場合は、とにかくあなたのクラスの名前を変更するほうが長持ちします。
名前空間を使用する代わりに、シンボルに接頭辞を付けて手動で名前空間を指定することもできます。私は何十年も使ってきた2つのライブラリを持っています。どちらもCライブラリとして始まります。ここで、everysymbolの前に "AK"または "SCWin"が付いています。 AK :: foo()はAKFoo()で、コードの5-10%密度が高く冗長度が低くなりますが、唯一のマイナス面は、問題がある場合は大きな問題になることです。 X-Windowsライブラリは、この点で優れていますが、いくつかの#defineを使用することを忘れている点が異なります。TRUEとFALSEは、XTRUEとXFALSEでなければなりません。 SybaseまたはOracleと名前空間が衝突し、同様にTRUEとFALSEが異なる値で使用されています(データベースの場合はASCIIの0と1)。これの1つの特別な利点は、プリプロセッサ定義にはほとんど当てはまりません。これの良い利点は、それがイブするプロジェクトの一部であることから有機的な傾斜を与えることです。実際は図書館です。私の大規模なアプリケーションでは、すべてのウィンドウクラスの接頭辞はWin、すべての信号処理モジュールのModなどです。これらのいずれかが再利用される可能性はほとんどないため、各グループをライブラリにしても実用的なメリットはありませんが、数秒でプロジェクトがサブプロジェクトに分割されることが明らかになります。
これは私が他のどの答えにも見いだせなかった見方である:1つの名前空間だけを使う。ほとんどの回答によれば、名前空間が良くない主な理由は、あなたが矛盾する関数名を持つことができ、それが全体の混乱を招く可能性があるということです。ただし、名前空間を1つだけ使用している場合はこれは起こりません。どのライブラリを使用するのかを決めて(おそらくusing namespace std;
)、それを使い続けます。
見えないライブラリ接頭辞があると考えることができます - std::vector
は単なるvector
になります。私の考えでは、これは両方の長所のうちの最良のものです。一方では(名前空間で意図されているように)あなたがしなければならないタイピングの量を減らします。名前空間プレフィックスのない関数やオブジェクトがある場合 - あなたはそれがあなたが宣言した一つの名前空間からのものであることを知っています。
あなたが世界的にそれを使うことに決めるならば - 覚えているだけで - 他の人をローカルに使わないでください。これは、ローカルネームスペースが便利なことに多様性を提供するため、グローバルネームスペースよりも便利であるという他の答えに戻ります。