첫째, 몇 가지 용어 :
- using-declaration :
using std::vector;
- 지시어 사용 :
using namespace std;
헤더 파일의 전역 범위에서 사용되지 않는 한 using-directives 를 사용 하는 것이 좋습니다. 그래서
using namespace std;
.cpp 파일에있는 것은 실제로 문제가되지 않으며, 문제가있는 것으로 밝혀지면 완전히 제어 할 수 있습니다 (원하는 경우 특정 블록으로 범위를 지정할 수도 있음). 수많은 std::
한정자로 코드를 어지럽히는 특별한 이유는 없습니다. 단지 시각적 노이즈가됩니다. 그러나 std
코드 에서 네임 스페이스 의 전체 이름을 사용하지 않는 경우 지시문을 생략해도 문제가 없습니다. 그것은 팽팽한 것입니다. 지시가 필요하지 않다면 그것을 사용할 필요가 없습니다.
마찬가지로 네임 스페이스의 특정 유형에 대해 몇 가지 using-declaration ( using-directives 대신)을 사용할std
수 있다면 해당 특정 이름 만 현재 네임 스페이스로 가져 오지 말아야 할 이유가 없습니다. 마찬가지로, 단일 using-directive가 트릭을 수행 할 때 25 또는 30 개의 using-declaration을 갖는 것은 미친 짓이고 부기 번거로울 것이라고 생각합니다.
그것은 당신이 항상 있다는 것을 명심하는 것이 좋다 해야한다 사용하여 선언을 사용. Effective C ++, Third Edition에서 Scott Meyers의 "항목 25 : 던지지 않는 스왑에 대한 지원 고려"를 참조하십시오. 일반적인 템플릿 함수가 매개 변수화 된 유형에 대해 '최상의'스왑 메서드를 사용하도록하려면 using-declaration 및 인수 종속 조회 (일명 ADL 또는 Koenig 조회)를 사용해야합니다.
template< typename T >
void foo( T& x, T& y)
{
using std::swap; // makes std::swap available in this function
// do stuff...
swap( x, y); // will use a T-specific swap() if it exists,
// otherwise will use std::swap<T>()
// ...
}
네임 스페이스를 많이 사용하는 다양한 언어의 공통 관용구를 살펴 봐야한다고 생각합니다. 예를 들어 Java 및 C #은 네임 스페이스를 광범위하게 사용합니다 (C ++보다 더 많이 사용됨). 네임 스페이스 내의 이름이 해당 언어에서 사용되는 가장 일반적인 방법은 using-directive에 해당하는 것과 함께 한꺼번에 현재 범위로 가져 오는 것입니다. 이것은 광범위한 문제를 일으키지 않으며, 문제가되는 몇 번은 정규화 된 이름을 통해 문제의 이름을 처리하거나 별칭을 지정하여 '예외'기준으로 처리됩니다. C ++에서 수행 할 수있는 것처럼.
Herb Sutter와 Andrei Alexandrescu는 "Item 59 : Do n't write namespace usings in a header file or before an #include"of their book, C ++ Coding Standards : 101 Rules, Guidelines, and Best Practices :
요컨대 : 지시문 뒤에 구현 파일에서 선언과 지시문을 자유롭게 사용하여 네임 스페이스를 사용할 수 있고 사용해야 #include
합니다. 반대로 반복되는 주장에도 불구하고 선언과 지시문을 사용하는 네임 스페이스는 악의가 없으며 네임 스페이스의 목적을 무너 뜨리지 않습니다. 오히려 네임 스페이스를 사용 가능하게 만듭니다.
Stroupstrup은 "The C ++ Programming Language, Third Edition"에서 "글로벌 네임 스페이스를 오염시키지 마십시오"라는 말로 자주 인용됩니다. 그는 실제로 (C.14 [15])라고 말하지만 C.10.1 장에서 다음과 같이 말합니다.
사용 선언은 로컬 영역에 이름을 추가한다. 사용-지시어는 하지 않습니다; 단순히 선언 된 범위에서 액세스 가능한 이름을 렌더링합니다. 예를 들면 :
namespaceX {
int i , j , k ;
}
int k ;
void f1()
{
int i = 0 ;
using namespaceX ; // make names from X accessible
i++; // local i
j++; // X::j
k++; // error: X::k or global k ?
::k ++; // the global k
X::k ++; // X’s k
}
void f2()
{
int i = 0 ;
using X::i ; // error: i declared twice in f2()
using X::j ;
using X::k ; // hides global k
i++;
j++; // X::j
k++; // X::k
}
로컬로 선언 된 이름 (일반 선언 또는 using-declaration에 의해 선언 됨)은 동일한 이름의 로컬이 아닌 선언을 숨기고 선언 지점에서 이름의 불법적 인 오버로딩이 감지됩니다.
대한 모호성 오류를 참고 k++
에서
f1()
. 전역 이름은 전역 범위에서 액세스 할 수있는 네임 스페이스의 이름보다 우선하지 않습니다. 이는 우발적 인 이름 충돌에 대한 상당한 보호를 제공하며, 중요한 것은 전역 네임 스페이스를 오염시켜 얻을 수있는 이점이 없음을 보장합니다.
많은 이름을 선언하는 라이브러리가 using-directive를 통해 액세스 가능하도록 만들 때 사용하지 않는 이름의 충돌이 오류로 간주되지 않는다는 것이 중요한 이점입니다.
...
기존의 C 및 C ++ 프로그램에 비해 네임 스페이스를 사용하는 새 프로그램에서 전역 이름 사용이 급격히 줄어들기를 바랍니다. 네임 스페이스에 대한 규칙은 전역 범위를 오염시키지 않도록주의하는 사람보다 전역 이름의``게으른 ''사용자에게 이점을 제공하지 않도록 특별히 제작되었습니다.
그리고 '글로벌 이름의 게으른 사용자'와 같은 이점이있는 이유는 무엇입니까? using-directive를 활용 하여 네임 스페이스의 이름을 현재 범위에서 안전하게 사용할 수 있도록합니다.
std
사용 지시문 (뒤에 지시문을 배치하여)을 적절히 사용하여 범위에서 사용할 수 있는 네임 스페이스 의 이름은 전역 네임 스페이스를 오염 #includes
시키지 않습니다 . 그 이름을 쉽게 사용할 수 있고 충돌에 대한 지속적인 보호를 제공합니다.