태그 보관물: c++-faq

c++-faq

“네임 스페이스 std를 사용하는 이유”; 나쁜 연습으로 간주? 나는 쓰는

나는 쓰는 것을 다른 사람에 의해 들었다 using namespace std;코드에서하는 것은 잘못이다, 내가 사용해야 std::cout하고 std::cin직접 대신.

using namespace std;나쁜 습관 으로 간주됩니까? 모호한 변수 (이름 std공간 의 함수와 동일한 이름을 공유하는 변수)를 선언하는 것이 비효율적 입니까? 성능에 영향을 줍니까?



답변

이것은 성능과 전혀 관련이 없습니다. 그러나 이것을 고려하십시오 : Foo와 Bar라는 두 개의 라이브러리를 사용하고 있습니다 :

using namespace foo;
using namespace bar;

모든 것이 잘 작동하며 문제없이 Blah()Foo와 Quux()Bar에서 전화 할 수 있습니다. 그러나 언젠가는 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공간이 많은 것이 식별자의 톤이 매우 일반적인 것들 (생각 list, sort, string, iterator, 너무 다른 코드에 표시 할 가능성이 높다 등).

이 가능성을 고려 경우가 있었다 질문 물었다 거의 정확히이 (인해 생략에라는 잘못된 기능 일어난 곳 스택 오버플로 여기에 std::나는이 대답을 준 후 반년에 대한 접두사). 다음은 이러한 질문의 또 다른, 더 최근의 예이다. 따라서 이것은 실제 문제입니다.


하나 더 많은 데이터 포인트가 있습니다. 수년 전에도 표준 라이브러리의 모든 것을 접두사로 사용하는 것이 성가신 것으로 나타났습니다 std::. 그런 다음 using함수 범위를 제외하고 지시문과 선언이 모두 금지 되도록 시작한 프로젝트에서 작업했습니다 . 뭔지 맞춰봐? 접두사를 작성하는 데 익숙해지기까지는 대부분 몇 주가 걸렸으며, 몇 주 후에 대부분의 사람들은 실제로 코드를 더 읽기 쉽게 만들었다는 데 동의했습니다 . 그 이유는 다음과 같습니다. 짧거나 긴 산문을 좋아하든간에 주관적이지만 접두사가 코드에 명확성을 추가합니다. 컴파일러뿐만 아니라 어떤 식별자가 참조되는지 쉽게 알 수 있습니다.

10 년 동안이 프로젝트는 수백만 줄의 코드로 성장했습니다. 이러한 논의가 계속 반복되기 때문에 (허용 된) 함수 범위가 using실제로 프로젝트에서 얼마나 자주 사용되는지 궁금 했습니다. 나는 그 소스를 grep하고 그것이 사용 된 한두 곳에서만 발견했다. 나에게 이것은 일단 시도하면 개발자가 std::100 kLoC마다 지시문을 사용할 수있는 곳에서도 지시문을 사용할 정도로 고통스럽지 않다는 것을 나타냅니다 .


결론 : 모든 접두사를 명시 적으로 사용하면 아무런 해를 끼치 지 않으며 익숙해지기가 거의 없으며 객관적인 이점이 있습니다. 특히, 컴파일러와 독자가 코드를 쉽게 해석 할 수있게 해주므로 코드 작성시 주요 목표가되어야합니다.


답변

using namespace클래스의 헤더 파일을 넣을 때의 문제는 클래스를 사용하려는 사람 (헤더 파일 포함)을 다른 네임 스페이스에서도 ‘사용'(즉, 모든 것을 볼 수 있도록)해야한다는 것입니다.

그러나 (개인) * .cpp 파일에 using 문을 자유롭게 넣을 수 있습니다.


일부 사람들 using은 cpp 파일 의 문장 이 헤더보다 낫지 만 (헤더 파일을 포함하는 사람들에게 영향을 미치지 않기 때문에) 여전히 내 생각에 동의하지 않는다는 점에주의하십시오 . 코드에 따라 클래스 구현을 유지하기가 더 어려울 수 있기 때문에 좋습니다 . 이 C ++ Super-FAQ 항목 은 다음과 같이 말합니다.

using-directive는 레거시 C ++ 코드에 존재하며 네임 스페이스로 쉽게 전환 할 수 있지만 최소한 새로운 C ++ 코드에서는 사용하지 않아야합니다.

FAQ는 두 가지 대안을 제안합니다.

  • 사용 선언 :

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • std :: 만 입력하면

    std::cout << "Values:";

답변

최근에 Visual Studio 2010 에 대한 불만이 있었습니다. 거의 모든 소스 파일에 다음 두 줄이 있다는 것이 밝혀졌습니다.

using namespace std;
using namespace boost;

많은 Boost 기능이 C ++ 0x 표준으로 들어가고 Visual Studio 2010에는 많은 C ++ 0x 기능이 있으므로 갑자기 이러한 프로그램이 컴파일되지 않았습니다.

따라서 피하는 using namespace X;것은 미래 보장의 한 형태이며, 사용중인 라이브러리 및 / 또는 헤더 파일을 변경해도 프로그램이 중단되지 않도록하는 방법입니다.


답변

짧은 버전 : using헤더 파일에 전역 선언이나 지시문을 사용하지 마십시오 . 구현 파일에서 자유롭게 사용하십시오. Herb SutterAndrei AlexandrescuC ++ 코딩 표준 에서이 문제에 대해 말한 내용은 다음과 같습니다 (강조를위한 대담은 내 것입니다).

요약

네임 스페이스 사용은 다른 사람에게 영향을주지 않는 편의를위한 것입니다. #include 지시문 앞에 using 선언 또는 using 지시문을 작성하지 마십시오.

Corollary : 헤더 파일에서 지시문이나 선언을 사용하여 네임 스페이스 수준을 쓰지 마십시오. 대신, 모든 이름을 명시 적으로 네임 스페이스로 규정하십시오. (두 번째 규칙은 첫 번째 규칙을 따릅니다. 헤더는 다른 헤더 #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…) 보다 낫습니다 (ADL ( 인수 종속 조회 )을 통해).


답변

전 세계적으로 사용하지 마십시오

전 세계적으로 사용될 때만 “나쁜”것으로 간주 됩니다 . 때문에:

  • 프로그래밍하고있는 네임 스페이스를 복잡하게 만듭니다.
  • 많은을 사용할 때 독자는 특정 식별자의 출처를 알기가 어렵습니다 using namespace xyz.
  • 소스 코드를 읽는 다른 독자에게는 무엇이든지 , 가장 자주 읽는 독자에게는 더 사실입니다. 1 ~ 2 년 후에 다시 와서보세요 …
  • 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잠재적 인 과부하를 찾아서 선택하도록 구현 이 변경되었습니다.