C ++で「using」を使用するか、それを避けますか?


17

ADLによるわずかに異なるセマンティクスの割引、一般的な使用方法using、およびその理由 状況に依存しますか(たとえば、#includedになるヘッダーとそうでないソースファイル)。

また、私は好むべきです::std::std::

  1. 名前空間レベルusing namespace

    using namespace std;
    
    pair<string::const_iterator, string::const_iterator>
    f(const string &s) {
        return make_pair(s.begin(), s.end());
    }
  2. 完全に明示的であること:

    std::pair<std::string::const_iterator, std::string::const_iterator>
    f(const std::string &s) {
        return std::make_pair(s.begin(), s.end());
    }
  3. 名前空間レベルのusing宣言:

    using std::pair;
    using std::string;
    
    pair<string::const_iterator, string::const_iterator>
    f(const string &s) {
        return make_pair(s.begin(), s.end());
    }
  4. 関数ローカルusing宣言:

    std::pair<std::string::const_iterator, std::string::const_iterator>
    f(const std::string &s) {
        using std::make_pair;
        return make_pair(s.begin(), s.end());
    }
  5. 機能ローカルusing namespace

    std::pair<std::string::const_iterator, std::string::const_iterator>
    f(const std::string &s) {
        using namespace std;
        return make_pair(s.begin(), s.end());
    }
  6. 他に何か?

これは、C ++ 14より前を想定しているため、を使用したreturn-type-deductionはありませんauto


2
開始点については、stackoverflow.com / questions / 1265039 / using-std-namespaceを参照してください。
AProgrammer

@AProgrammer:ああ、私の質問の一部に答えてくれるリンクをありがとう。:)それでも::std::vs について疑問に思ってstd::います。
Mehrdad

4
stdしかし、私は何もせずに使用しています。std名前空間を定義している人がトラブルを求めています(そして、おそらくほとんどの人が使用しているのstdではなく、使用していることを利用して検索しています::std)。
AProgrammer

回答:


25

usingヘッダーでの使用は避けてください。名前空間の目的が損なわれるためです。

ソースファイルで使用しても構いませんが、場合によっては回避できます(たとえばusing std)。

ただし、ネストされた名前空間を取得した場合は問題ありません。

namespace A {
namespace B {
namespace C {
class s;
} // C
} // B
namespace D{
using B::C::s;
} // D
} // A

6
+1 using名前空間が最初に使用される理由を完全に説明せずにキーワードを使用するように指示するチュートリアルと大学のコースがいくつあるかは驚くべきことです。
ジェフリースウィーニー

人々は、iostreamや文字列などの使用を続けたいと考えています。彼らはstd:を入力する必要はありません:何かを使用したいたびに、またはコードの前に置く別の定型句を覚えておく必要があります。 。:(
Colen

typedef std :: string sstring;のようなものでしょうか。代わりになりますか?
ジョルジオ

1
@コーレン:これらの貧しい人々はusing std::cout友人や友人を使うことができますcoutが、すでに恐ろしいほど長い名前ではないようです。
ベンジャミンバニエ

1
「私の最初のC ++クラス」の最初の日に大学生である場合、それはあなたが理解できない構文エラーを引き起こす可能性があるさらに別のものです。私たちは経験豊富なプログラマーであるため、簡単に把握できますが、言語を学習しようとする場合、必要のないことを心配する必要があります。
コレン

11

ソースファイルにusingステートメントを配置するときは、必要なものを入力してください。例えば:

using std::string;
using std::ostringstream;

ここでの問題は、もしあなたが

using namespace std;

すべての単一のものをstdからグローバル名前空間に取り込みます。これは、stdでまったく知らなかったものと一致する名前を誤ってコード内で使用した場合、非常に興味深いエラーメッセージにつながります。必要なものを引き込むだけであれば、その問題は発生しません(または、より正確には、コードに取り組む次のプログラマーはその問題を発生しません)。


または、using namespace関数スコープ内で問題を回避できます。
タマスゼレイ

2
@fish-実際には、関数スコープで「名前空間を使用する」ことで問題が回避されるわけではなく、問題が発生する可能性のあるスペースが制限されるだけです。そして、すべての関数に「名前空間の使用」を追加しても、グローバルに実行する場合とほとんど変わりません。
マイケルコーネ

C ++では実際に関数レベルで型を宣言できますが、一般的なことではありません。それ以外に、名前の衝突の可能性はコンパイラの出力から簡単に見つけることができます(しかし、これはそれらを妨げないことは正しいです)。
タマスシェレイ

2

VJovicが示すようusingに、ヘッダーファイルでは使用しないでください。usingソースファイルが予期しない方法で、ヘッダーファイル内の現在のコンパイル単位(.cppファイル)に影響します。

using namespaceまた、ソースファイルでは避ける必要があります。これにより、すべてのシンボルがソースファイルと同じスコープになります。名前空間の特定のシンボルを使用すると、読者が何をしているのかがより明確になります。


2
実用的な懸念として、コードが一般的に使用される名前を上書きしない限り、すべてのオブジェクトに添付するusing namespace JoystickModuleよりも、.cppファイルの先頭に表示する方がはるかに望ましいJoystickModule::です。
アレックスP

@AlexP:それはまさに私がやる方法です。using私が現在取り組んでいる自分の名前空間についての1つのステートメントと、他のすべては名前空間のままです。
ベンジャミンクロスター

「名前空間から特定のシンボルを使用する」について詳しく説明する必要があります。使用するたびに各シンボルに接頭辞を付けて読みやすくするのではなく、明示的なシンボルの巻き上げを使用することを好みます。using SomeNameSpace::SomeSymbol。これにより、すべてのシンボルがネームスペースから現在のスコープに移動することを回避できます。
ビル・ドアの

0

usingヘッダーに書き込むことは、あらゆる種類の厄介デバッグ不可能バグを作成する最良の方法です。これをしないでください。

using namespace XYZソースファイルへの書き込みは少し改善されていますが、それでも無数の頭痛の種になります。安全な方法は、使用しているものを明示的に指定することですusing Foo::Bar

次のBar.cppがあるとします。

//Bar.cpp
using namespace Foo;
namespace
{
    double increment(double v) { return (v + 1); }
}

void Bar::someFunction()
{
    //...
    int currentIndex = 0;
    int nextIndex = increment(currentIndex);
    //...
}

この関数は、ある日まで-関連クラスのコードを変更しなかったように見える-動作が変化しました:突然1つずれてcurrentIndexいるようです。最近の変更を掘り下げると、コードにリモートで関連する変更も発見されません。

最終的に、原因を発見します:
あなたは(間接的に)Foo.hどこかに含めます。Foo名前空間のファイルに、新しい関数が追加されました。

//Foo.h
namespace Foo
{
    //...
    int& increment(int& v) { v += 1; return v; };
    //...
}

そのためunambigiously良く一致しているincrement(int)、あなたの関数よりもincrement(double)-そう、今Foo::increment()機能がによって呼び出されるBar::someFunction()代わりに。おっと。

(そして、もしあなたがインクルードツリーのどこかに非常によくusingあるusing namespace FooかもしれないHeadersで書くなら...)

だから... ヘッダーには何も書かないでください。また、ソースファイルusingに書くことには注意してusing namespaceください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.