C ++에서`using`을 사용하거나 피합니까?


17

ADL로 인해 미묘하게 다른 시맨틱을 할인, 어떻게 일반적으로 사용해야 using하며 왜? 상황에 따라 #include다릅니 까 (예 : 헤더 가 아닌 소스 파일이되는 헤더 )?

또한, ::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 std::pair;
    using std::string;
    
    pair<string::const_iterator, string::const_iterator>
    f(const string &s) {
        return make_pair(s.begin(), s.end());
    }
  4. 함수 로컬 사용 선언 :

    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 이전을 가정하고 있으므로를 사용하여 반환 유형을 공제하지 않습니다 auto.


2
시작점 은 stackoverflow.com/questions/1265039/using-std-namespace 를 참조하십시오 .
AProgrammer

@ AProgrammer : 아, 내 질문의 일부에 답변하는 링크 주셔서 감사합니다. :) 정지에 대해 궁금 ::std::std::하지만.
user541686

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네임 스페이스를 사용하여 시작하는 이유에 대한 철저한 설명없이 키워드 를 사용하도록 지시하는 자습서 및 대학 과정이 얼마나 놀라운 지 놀랍 습니다.
Jeffrey Sweeney 13:24에

사람들은 요오드 스트림, 문자열 등을 사용하고 싶어합니다. 그들은 std :를 입력하고 싶지 않습니다 : 매번 물건을 사용하고 싶거나 코드 앞에 넣어야 할 또 다른 상용구를 기억해야합니다. 잊어 버릴 경우 도움이되지 않는 오류가 발생합니다 . :(
Colen

typedef std :: string sstring과 같은 것이겠습니까? 대안이 되겠습니까?
조르지오

1
@Colen :이 불쌍한 영혼은 using std::cout친구와 친구를 사 can 수 있지만 cout이미 끔찍하게 긴 이름은 아닙니다 .
Benjamin Bannier

1
"내 첫 C ++ 클래스"의 첫날에 대학생이라면 이해하지 못하는 구문 오류가 발생할 수있는 또 다른 문제입니다. 우리는 숙련 된 프로그래머이기 때문에 쉽게 알 수 있지만 언어를 배우려고 할 때 필요하지 않다는 것에 대해 걱정해야 할 또 다른 사항입니다.
Colen

11

소스 파일에 using 문을 넣을 때는 PLEASE를 사용하여 필요한 것을 가져 오십시오. 예를 들어 :

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

여기서 문제는 당신이 할 경우

using namespace std;

std에서 전역 네임 스페이스로 모든 단일 항목을 가져옵니다. 코드에서 실수로 std에서 완전히 알지 못하는 것과 일치하는 이름을 사용할 때 매우 흥미로운 오류 메시지가 나타납니다. 원하는 것을 끌어 들이면 문제가 발생하지 않습니다 (또는 더 정확하게 말하면 코드에서 작업 할 다음 프로그래머에게는 해당 문제가 없습니다).


또는 using namespace기능 범위 내에서 문제를 피할 수 있습니다 .
Tamás Szelei

2
@fish-실제로 함수 범위에서 '네임 스페이스 사용'을 수행해도 문제가 발생하지 않으며 문제가 발생할 수있는 공간을 제한합니다. 그리고 모든 함수에 '사용 네임 스페이스'를 넣으면 전 세계적으로 수행하는 것과 크게 다르지 않습니다.
Michael Kohne

실제로 C ++은 함수 수준에서 유형을 선언 할 수 있지만 일반적인 것은 아닙니다. 그 외에는 가능한 이름 충돌이 컴파일러 출력에서 ​​쉽게 알 수 있습니다 (그러나 이것이 충돌하지 않는 것이 맞습니다).
Tamás Szelei

2

VJovic에서 알 수 있듯이 using헤더 파일 에는 사용하지 마십시오 . using헤더 파일에서는 소스 파일이 예상하지 못한 방식으로 현재 컴파일 단위 (.cpp 파일)에 영향을줍니다.

using namespace소스 파일에서도 피해야합니다. 이것은 모든 심볼을 소스 파일과 동일한 범위로 가져옵니다. 네임 스페이스에서 특정 기호를 사용하면 사용자가하는 일이 더 명확합니다.


2
실제로는 코드가 일반적으로 사용되는 이름을 재정의하지 않는 using namespace JoystickModule한 .cpp 파일의 시작 부분 JoystickModule::에서 모든 객체에 첨부되는 것보다 훨씬 낫 습니다.
Alex P

@ AlexP : 정확히 내가하는 방법입니다. using현재 작업중 인 내 네임 스페이스에 대한 하나의 진술과 그 밖의 모든 네임 스페이스는 유지됩니다.
Benjamin Kloster '

"네임 스페이스의 특정 심볼 사용"에 대해 자세히 설명해야합니다. 가독성을 높이는 데 도움이되지 않는 모든 용도에 각 기호를 접두사로 사용하는 대신 명시적인 기호 게양을 사용하는 것이 좋습니다. using SomeNameSpace::SomeSymbol. 이렇게하면 네임 스페이스에서 현재 범위로 모든 심볼이 이동하지 않습니다.
Bill Door

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);
    //...
}

이 기능은 어느 날, 벌금을했다 - 겉으로는 해당 클래스의 코드를 변경하지 않고 - 그 동작이 변경 : 갑자기 currentIndex항상 것 같다 하나 떨어져 . 최근 변경 사항을 살펴보면 코드와 원격으로 관련된 변경 사항도 발견되지 않습니다.

결국 원인을 발견하게됩니다 :
당신은 (간접적으로) Foo.h어딘가에 포함 합니다. Foo 네임 스페이스의 파일에 새로운 기능이 추가되었습니다.

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

어느 것이 increment(int)함수보다 명확하게 더 잘 맞습니다. increment(double)이제 Foo::increment()함수가 Bar::someFunction()대신 호출 됩니다. 으악.

(그리고 포함 트리의 어느 곳에 나 있을 수 using있는 헤더 를 작성한다면 ...)using namespace Foo

따라서 ... 헤더에 쓰지 말고 소스 파일에 쓰지 않도록using 주의 using namespace하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.