“네임 스페이스 사용”오염이란 무엇입니까?


15

나는 구글 코딩 가이드를 찾고 있었어요 [여기] 그리고 그들은 하나가 사용하지 않는 것이 좋습니다 using namespace또는 namespace::function- 내가 잘못 해석하지 않은 경우.

이것도 std마찬가지입니까? cout<<그것 없이는 작동하지 않습니다. 이 책 은 같은 것을 권장합니다. 그렇다면 또는 cout<<없이 사용하는 방법은 무엇입니까?using namespace std;std::cout<<

권장되는 방법은 무엇입니까? std::cout<<? 대부분의 C ++ 교재는 초보자들에게 using namespace std;나쁜 코딩 연습을 전파하고 있습니까?

답변:


18

Google 표준을 읽으면 using namespace foo;어디에서나 지시문을 사용할 수 없습니다 . 이 지시어는 네임 스페이스에 선언 된 모든 것을 가져오고 충돌과 예기치 않은 동작의 일반적인 원인입니다. 다른 사람들은 매우 일반적인 것을 인용했습니다 : 당신은 어딘가에 자신의 max 또는 min 메소드를 가지고 있으며 누군가가 당신의 메소드에 헤더를 포함하는 src 파일에서 충돌합니다.using namespace std;

어떤 곳에서는 사용 선언을 할 수 있습니다. using ::foo::bar;

사람들은 많은 타이핑을 저장하지 않기 때문에 코드에 지시문을 사용하는 것을 좋아하지만 위험이 따릅니다. cout 문이 많은 파일이 있으면 std :: cout을 100 번 입력하고 싶지는 않지만 :: std :: cout을 사용하여 간단히 말할 수 있습니다. 나는 이것을 변수 선언처럼 취급한다 : 그것들을 필요한 곳으로 범위를 정한다. 10의 파일에서 하나의 함수가 출력을 작성해야하는 경우 상단에 cout way를 선언하지 말고 실제 출력을 수행하는 함수에 넣으십시오.

#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;
}

출력을하는 몇 줄만 있으면 약간 극단적이지만 아이디어를 얻습니다.

입력을 최소화하기 위해 별명 또는 typedef를 사용할 수 있습니다. std :: find를 찾을 수는 없습니다.하지만 수십 개의 모듈이있는 거대한 소스 세트가 있으며 때로는 코드를 작성해야합니다 console_gui::command_window::append("text"). 잠시 후에 지루해지고 많은 긴 줄이 생깁니다. 나는 모두 같은 것을 위해

typedef console_gui::command_window cw;
cw::append("text");

별칭이 로컬 범위에서 수행되고 코드를 읽을 수 있도록 충분한 컨텍스트를 유지하는 한.


1
감사! 이것은 정말 도움이됩니다. 좋은 예제로 왜 나쁜지 설명 할뿐만 아니라 좋은 예제로 솔루션을 지적했습니다. :-)
주님 Loh.

1
BTW : std::endl명시 적 플러시에 사용 하는 것은 stdout/ stderr일반적으로 상당히 불필요한 데, 그 스트림은 어쨌든 stdout/에 묶여 stderr있습니다. 심지어 속도가 약간 느려집니다.
중복 제거기

8

그 이유는 다음과 같습니다. 1) 네임 스페이스의 전체 목적을 무효화하여 이름 충돌을 줄입니다. 2) 전역 네임 스페이스에 using 지시문으로 지정된 전체 네임 스페이스를 사용할 수 있습니다.

예를 들어, 자신의 max () 함수를 포함하고 정의하면 std :: max ()와 충돌합니다.

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

기본 설정은 std :: member_you_wish_to_use를 사용하는 것입니다. 명시 적으로 사용할 네임 스페이스를 명시하기 때문입니다.


나는 이것이 std::max()네임 스페이스 접두사와 함께 사용해야한다는 것을 의미한다고 가정 합니다. 아니면 내가 착각합니까?
주님로.

3
"사용 네임 스페이스 std;"를 넣으면 자신의 최대 함수 (또는 std 네임 스페이스에 이미 정의 된 다른 이름)를 정의하면 코드에서 오류가 발생합니다.
Chewy Gumball

1
그것은 using지시문에 주의를 기울여야한다는 것을 의미합니다 .이 경우 max () 함수를 정의하고 <algorithm>을 포함하면 max () 함수가 중단됩니다. 이것은 간단한 경우이지만 당신은 당신이 무엇을 깰 수 있는지 모릅니다. 라이브러리를 깨지 않았는지 확인하려면 전체 라이브러리를 알아야하지만 나중에 코드가 손상되는지 (예 : 이름 충돌) 알 수 없습니다.
ApplePie

6

제공하는 링크 인용 :

.cc 파일의 어느 곳에서나 .h 파일의 함수, 메서드 또는 클래스에서 사용 선언을 사용할 수 있습니다.

// .cc 파일에서 OK

// .h 파일의 함수, 메서드 또는 클래스에 있어야합니다.

:: foo :: bar; 사용

Google 스타일을 사용하면 전역 컨텍스트에서 네임 스페이스 가져 오기를 사용할 수 없지만 로컬 네임 스페이스에서는 네임 스페이스를 가져올 수 있습니다.

선언을 사용하면 제한적이고 명확하게 보이는 코드 부분에만 영향을 미치는 모든 곳에서 완벽하게 허용됩니다.

전역 컨텍스트를 오염 시키면 관련 코드가 영향을받습니다 (헤더를 사용하여 결함이 있음). 로컬 컨텍스트에서 그렇게 할 때 아무 일도 일어나지 않습니다.


우리는 같은 표준을 가지고 있습니다. 일부 직원은 로컬로 긴 네임 스페이스를 typedef합니다. 예 : typedef foolicious :: barlicious fb; fb :: 음료 d;
Michael Mathews

1

그들은 사용하는 네임 스페이스 또는 네임 스페이스 : 함수를 사용하지 않는 것이 좋습니다-잘못 해석하지 않으면.

그렇습니다. 권고는 using namespace지시어 에만 적용됩니다 (일반적으로 abusing namespace유머가 아닌 이라고 함 ). 함수 또는 객체의 정규화 된 이름 (예 :)을 사용하는 것이 좋습니다 std::cout.


1

질문에 유용한 답변이 있지만 세부 사항이 너무 짧아 보입니다.

대부분의 프로그래머는 처음에는 using키워드와 namespace사용법에 약간의 혼란을 겪 습니다. 선언지시문 은 다소 동일 하기 때문에 참조를 찾아서 배우려고해도 키워드와 사용법에 대한 설명 은 다소 복잡합니다. 둘 다 d로 시작하는 비교적 추상적 인 단어 입니다.

네임 스페이스 내 식별자는 네임 스페이스를 명시 적으로 명명하여 액세스 할 수 있습니다.

myNamespace::myIdent

이것은 더 많은 키를 입력 할 수 있습니다. 그러나 대부분의 식별자가 같은 방식으로 접두어를 사용하면 코드의 중요성이 줄어들 수도 있습니다. using키워드는이 네임 스페이스의 단점을 방지하는 데 도움이됩니다. using컴파일러 수준에서 작동 하기 때문에 (매크로가 아님), 그 효과는 사용 된 전체 범위에서 지속됩니다. 따라서 Google 스타일은 잘 정의 된 범위 (예 : 헤더 파일의 클래스 또는 cpp 파일의 함수)로 사용을 제한합니다.

물론 선언사용 하는 것에는 차이가 있습니다.

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

지시어를 사용하여

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

넓은 범위에서 사용될 경우 후자는 훨씬 더 혼란을 초래합니다 .


1

여기 있습니다 :

#include <iostream>

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

이런 식으로 작성하면 지시문 및 선언을 사용하는 동시에 오류가 발생하기 쉬운 ADL을 피할 수 있습니다.

이것은 냉소적 인 대답이 될 것입니다. :-디

나는 이것에 대해 Google의 Herb Sutter를 사용하고 있습니다. C ++ 코딩 표준에서 :

#include 지시문 다음에 구현 파일에서 선언 과 지시문을 사용하여 네임 스페이스를 자유롭게 사용할 수 있으며 사용해야 합니다. 반대로 반복되는 주장에도 불구하고 선언과 지시문을 사용하는 네임 스페이스는 악의적이지 않으며 네임 스페이스의 목적을 무시하지 않습니다. 오히려 네임 스페이스를 사용할 수 있게 만드는 요소 입니다.

using지시문 을주의 깊게 피하고 using선언 과 함께 사용하는 모든 것을 명시 적으로 지정 하여 천문학적으로 드물게 발생하는 잠재적 네임 스페이스 충돌에 대해 집착 할 수 있습니다. 그냥 가서 시작하십시오 using namespace std. 나는 생산성 관점에서 후자를 추천한다.

대부분의 C ++ 교재는 네임 스페이스 std를 사용하여 초보자를 가르칩니다. 그들은 나쁜 코딩 관행을 전파하고 있습니까?

당신이 저에게 물어 보면 그 반대는 위의 Sutter가 동의한다고 믿습니다.

이제는 커리어가 진행되는 동안 using수천만 개의 LOC에 걸친 코드베이스 지시어 의 직접적인 결과로 총 3 개의 네임 스페이스 충돌이 발생했습니다 . 그러나 3 가지 경우 모두 원래 C로 작성된 5 만 라인의 레거시 코드에 걸친 소스 파일에 있었으며 C ++로 개화하여 수십 개의 다른 라이브러리의 헤더를 포함하여 방대한 양의 서로 다른 함수 목록을 수행했습니다. 서사시 목록#includes 한 페이지에 걸친 . 서사시 혼란에도 불구하고 런타임 버그가 아닌 OSX (코드 작성에 실패한 OS)에서 빌드 오류가 발생했기 때문에 수정하기가 어렵지 않았습니다. 이 악몽 같은 방식으로 코드를 구성하지 마십시오.

헤더 파일의 지시문과 선언을 모두using하십시오. 그것은 단지 지체되었다. 그러나 소스 파일, 특히 #include지시문으로 가득 찬 전체 페이지가없는 소스 파일의 경우 Google에서 일하지 않는다면 땀을 흘리지 않습니다.

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