나는 다른 사람들이 using namespace std;
코드에서 잘못되었으며 std::cout
및 std::cin
직접 사용해야 합니다.
using namespace std;
이유는 무엇입니까? 나쁜 습관으로 간주됩니까? std
네임스페이스의 함수와 동일한 이름을 공유하는 변수)를 선언할 위험이 있습니까? 성능에 영향을 줍니까?
질문자 :akbiggs
나는 다른 사람들이 using namespace std;
코드에서 잘못되었으며 std::cout
및 std::cin
직접 사용해야 합니다.
using namespace std;
이유는 무엇입니까? 나쁜 습관으로 간주됩니까? std
네임스페이스의 함수와 동일한 이름을 공유하는 변수)를 선언할 위험이 있습니까? 성능에 영향을 줍니까?
이것은 성능과 전혀 관련이 없습니다. 그러나 이것을 고려하십시오. Foo 및 Bar라는 두 개의 라이브러리를 사용하고 있습니다.
using namespace foo; using namespace bar;
모든 것이 잘 작동하며 문제 없이 Foo에서 Blah()
를 호출하고 Bar에서 Quux()
그러나 어느 날 Foo 2.0의 새 버전으로 업그레이드하면 Quux()
라는 함수를 제공합니다. 이제 충돌이 발생했습니다. Foo 2.0과 Bar 모두 Quux()
를 전역 네임스페이스로 가져옵니다. 이것은 특히 함수 매개변수가 일치하는 경우 수정하는 데 약간의 노력이 필요합니다.
foo::Blah()
및 bar::Quux()
를 사용했다면 foo::Quux()
의 도입은 이벤트가 아니었을 것입니다.
Greg가 쓴 모든 것에 동의하지만 추가하고 싶습니다. Greg가 말한 것보다 더 나쁠 수 있습니다!
Quux()
함수를 도입할 수 있습니다. 이 함수는 몇 년 동안 코드에서 호출한 bar::Quux()
Quux()
대한 일부 호출에 대해 명확하게 더 잘 일치합니다. 그런 다음 코드는 여전히 컴파일 되지만 자동으로 잘못된 함수를 호출하고 알고 있는 작업을 수행합니다. 그것은 상황이 얻을 수있는만큼 나쁩니다.
std
네임스페이스에는 수많은 식별자가 있으며 그 중 상당수는 다른 코드에도 나타날 가능성이 매우 높은 매우 일반적인 list
, sort
, string
, iterator
이것이 가능성이 없다고 생각한다면: 이 답변을 제공한 지 약 반년 후에 std::
접두어 생략으로 인해 호출된 잘못된 함수) Stack Overflow에 질문이 있었습니다. 다음 은 그러한 질문에 대한 더 최근의 또 다른 예입니다. 그래서 이것은 진짜 문제입니다.
데이터 포인트가 하나 더 있습니다. 몇 년 전에 표준 라이브러리의 모든 항목에 std::
접두사를 붙여야 하는 번거로움이 있었습니다. using
지시문과 선언문을 함수 범위를 제외하고 모두 금지하는 것으로 결정된 프로젝트에서 일했습니다. 뭔지 맞춰봐? 우리 대부분은 접두사를 작성하는 데 익숙해지는 데 몇 주가 걸렸고, 몇 주 후에 우리 대부분은 심지어 코드를 더 읽기 쉽게 만들었다는 데 동의했습니다. 그 이유가 있습니다. 더 짧거나 긴 산문을 좋아하는지 여부는 주관적이지만 접두사는 객관적으로 코드에 명확성을 추가합니다. 컴파일러뿐만 아니라 사용자도 참조하는 식별자를 더 쉽게 확인할 수 있습니다.
10년 만에 그 프로젝트는 수백만 줄의 코드로 성장했습니다. 이런 논의가 반복되다 보니 실제로 프로젝트에서 using
하는 (허용된) function-scope가 얼마나 자주 사용되는지 궁금했습니다. 나는 그것에 대한 소스를 grep'd 그리고 그것이 사용된 곳을 한두 곳만 찾았습니다. 나에게 이것은 한 번 시도하면 개발자가 std::
사용이 허용된 곳에서도 100kLoC마다 한 번이라도 using 지시문을 사용할 만큼 고통스럽다는 것을 찾지 못한다는 것을 나타냅니다.
결론: 모든 것에 명시적으로 접두사를 붙여도 해가 되지 않고 익숙해지는 데 시간이 거의 걸리지 않으며 객관적인 이점이 있습니다. 특히, 컴파일러와 인간 독자가 코드를 더 쉽게 해석할 수 있도록 하며, 이는 아마도 코드를 작성할 때 주요 목표가 되어야 합니다.
using namespace
를 넣을 때의 문제는 클래스를 사용하려는 사람(헤더 파일을 포함하여)이 다른 네임스페이스도 '사용'(즉, 모든 것을 볼 수 있음)하게 한다는 것입니다.
그러나 (개인) *.cpp 파일에 using 문을 자유롭게 넣을 수 있습니다.
하지만 때문에 - 어떤 사람들은 내이 같은 "자유로운 느낌"말에 동의하지 않는 것을주의 using
CPP 파일에 문이 더 나은 (그것은 당신의 헤더 파일을 포함 사람들에 영향을 미치지 않기 때문에) 헤더에보다, 그들은 여전히 생각 좋지 않다 (코드에 따라서는 유지 보수가 어려운 클래스의 구현을 만들 수 있기 때문에). 이 C++ Super-FAQ 항목 은 다음과 같이 말합니다.
using 지시문은 레거시 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 Sutter 와 Andrei Alexandrescu 가 C++ 코딩 표준 에서 이 문제에 대해 말한 내용은 다음과 같습니다.
요약
네임스페이스를 사용하는 것은 다른 사람에게 피해를 주기 위한 것이 아니라 사용자의 편의를 위한 것입니다. #include 지시문 앞에 using 선언이나 using 지시문을 작성하지 마십시오.
결론: 헤더 파일에서 지시문을 사용하거나 선언을 사용하여 네임스페이스 수준을 작성하지 마십시오. 대신 모든 이름을 명시적으로 네임스페이스로 한정하십시오. (두 번째 규칙은 첫 번째 규칙을 따릅니다. 왜냐하면 헤더는 그 뒤에 어떤 다른 헤더 #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;
많이 사용하면 독자는 특정 식별자의 출처를 파악하는 데 어려움을 겪을 것입니다. .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(...)` }
이것은 다음과 같은 마법을 수행합니다.
value_
에 대해 std::swap
을 선택합니다. 즉, void std::swap(int, int)
입니다.void swap(Child&, Child&)
구현되어 있으면 컴파일러가 이를 선택합니다.void std::swap(Child&,Child&)
하고 최상의 스왑을 시도합니다. C++11 에서는 이 패턴을 더 이상 사용할 이유가 없습니다. std::swap
의 구현이 잠재적인 과부하를 찾아 선택하도록 변경되었습니다.
오른쪽 헤더 파일을 가져오면 갑자기 hex
, left
, plus
또는 count
와 같은 이름이 전역 범위에 표시됩니다. std::
에 이러한 이름이 포함되어 있다는 사실을 모르는 경우 놀랄 수 있습니다. 이러한 이름을 로컬에서도 사용하려고 하면 상당한 혼란을 초래할 수 있습니다.
모든 표준 항목이 자체 네임스페이스에 있으면 코드 또는 다른 라이브러리와의 이름 충돌에 대해 걱정할 필요가 없습니다.
또 다른 이유는 놀라움입니다.
std::cout << blah
cout << blah
되면 다음과 같이 생각합니다. 이 cout
은 무엇입니까? 노멀 cout
인가요? 뭔가 특별한가요?
숙련된 프로그래머는 문제를 해결하는 모든 것을 사용하고 새로운 문제를 생성하는 것은 피하며, 바로 이러한 이유로 헤더 파일 수준 사용 지시문을 피합니다.
숙련된 프로그래머는 또한 소스 파일 내에서 이름의 완전한 자격을 피하려고 합니다. 이에 대한 사소한 이유는 합당한 이유가 없는 한 더 적은 수의 코드로 충분할 때 더 많은 코드를 작성하는 것이 우아하지 않기 때문입니다. 이에 대한 주요 이유는 인수 종속 조회(ADL)를 해제하기 때문입니다.
이 좋은 이유 는 무엇입니까? 프로그래머가 명시적으로 ADL을 끄고 싶을 때도 있고 명확하게 하고 싶을 때도 있습니다.
따라서 다음은 괜찮습니다.
나는 그것이 전역적으로 사용되어서는 안 된다는 데 동의하지만, namespace
에서처럼 로컬에서 사용하는 것이 그렇게 나쁘지는 않습니다. 다음은 "C++ 프로그래밍 언어"의 예입니다 .
namespace My_lib { using namespace His_lib; // Everything from His_lib using namespace Her_lib; // Everything from Her_lib using His_lib::String; // Resolve potential clash in favor of His_lib using Her_lib::Vector; // Resolve potential clash in favor of Her_lib }
이 예에서는 구성에서 발생하는 잠재적인 이름 충돌 및 모호성을 해결했습니다.
명시적으로 선언된 이름( His_lib::String
using namespace Her_lib
)에 의해 다른 범위에서 액세스할 수 있는 이름보다 우선합니다.
또한 나쁜 습관이라고 생각합니다. 왜요? 어느 날 나는 네임스페이스의 기능이 물건을 나누는 것이라고 생각했기 때문에 모든 것을 하나의 글로벌 백에 던지는 것으로 망쳐선 안 된다.
그러나 'cout'과 'cin'을 자주 사용하는 경우 다음과 같이 작성합니다. using std::cout; using std::cin;
#include
와 함께 전파되므로 헤더 파일에서는 절대 사용하지 마십시오). 제 생각에 제정신인 사람은 스트림 cout
또는 cin
이름을 지정하지 않을 것입니다. ;)
코드를 보고 그것이 무엇을 하는지 아는 것은 좋은 일입니다. std::cout
보면 std
cout
스트림이라는 것을 알 수 있습니다. 내가 cout
를 보면 나는 모른다. std
라이브러리의 cout
스트림일 수 있습니다. int cout = 0;
일 수 있습니다. 같은 기능에서 10줄 더 높습니다. 또는 해당 파일에 cout
이라는 static
무엇이든 될 수 있습니다.
이제 특별히 크지 않은 백만 줄의 코드 기반을 사용하여 버그를 찾고 있습니다. 즉, 이 백만 줄에서 해야 할 일을 하지 않는 한 줄이 있다는 것을 알 수 있습니다. cout << 1;
cout
이라는 static int
읽고 왼쪽으로 1비트 이동하고 결과를 버릴 수 있습니다. 버그를 찾고 있으니 확인해봐야겠네요. std::cout
를 보고 싶어하는 모습을 볼 수 있습니까?
당신이 교사이고 생계를 위해 코드를 작성하고 유지할 필요가 없다면 정말 좋은 생각인 것 중 하나입니다. 나는 (1) 코드가 무엇을 하는지 알고 있는 코드를 보는 것을 좋아합니다. (2) 나는 그것을 쓰는 사람이 그것이 하는 일을 알고 있다고 확신합니다.
복잡성 관리에 관한 모든 것입니다. 네임스페이스를 사용하면 원하지 않는 항목을 가져올 수 있으므로 디버그하기가 더 어려워질 수 있습니다(아마도). std:: 를 사용하면 모든 곳에서 읽기가 더 어렵습니다(더 많은 텍스트와 그 모든 것).
코스를 위한 말 - 당신이 할 수 있고 느낄 수 있는 방법으로 복잡성을 관리하십시오.
고려하다
// myHeader.h #include <sstream> using namespace std; // someoneElses.cpp/h #include "myHeader.h" class stringstream { // Uh oh };
이것은 간단한 예입니다. 20개의 포함 및 기타 가져오기가 있는 파일이 있는 경우 문제를 파악하기 위해 거쳐야 할 수많은 종속성이 있습니다. 더 나쁜 점은 충돌하는 정의에 따라 다른 모듈에서 관련 없는 오류가 발생할 수 있다는 것입니다.
끔찍하지는 않지만 헤더 파일이나 전역 네임스페이스에서 사용하지 않음으로써 두통을 줄일 수 있습니다. 매우 제한된 범위에서 이 작업을 수행하는 것이 좋습니다. 하지만 내 기능이 어디에서 왔는지 명확히 하기 위해 추가로 5자를 입력하는 데 문제가 있었던 적은 없습니다.
우려를 명확히 하기 위한 구체적인 예. 각각 고유한 네임스페이스가 있는 두 개의 라이브러리 foo
및 bar
namespace foo { void a(float) { /* Does something */ } } namespace bar { ... }
이제 다음과 같이 자신의 프로그램에서 foo
와 bar
함께 사용한다고 가정해 보겠습니다.
using namespace foo; using namespace bar; void main() { a(42); }
이 시점에서는 모든 것이 정상입니다. 프로그램을 실행하면 '무언가를 수행'합니다. 그러나 나중에 bar
를 업데이트하고 다음과 같이 변경되었다고 가정해 보겠습니다.
namespace bar { void a(float) { /* Does something completely different */ } }
이 시점에서 컴파일러 오류가 발생합니다.
using namespace foo; using namespace bar; void main() { a(42); // error: call to 'a' is ambiguous, should be foo::a(42) }
foo::a
의미한다는 것을 명확히 하기 위해 약간의 유지 관리가 필요합니다. 이는 바람직하지 않지만 다행히도 매우 쉽습니다(컴파일러가 모호한 것으로 표시 a
모든 호출 앞에 foo::
그러나 막대가 대신 다음과 같이 변경되는 대체 시나리오를 상상해 보십시오.
namespace bar { void a(int) { /* Does something completely different */ } }
이 시점에서 a(42)
대한 호출은 foo::a
bar::a
갑자기 바인딩되고 '무언가'를 수행하는 대신 '완전히 다른 것'을 수행합니다. 컴파일러 경고 또는 아무것도 없습니다. 프로그램은 이전과 완전히 다른 작업을 조용히 시작합니다.
네임스페이스를 사용하면 이와 같은 시나리오가 발생할 위험이 있습니다. 이것이 사람들이 네임스페이스를 사용하는 것을 불편하게 여기는 이유입니다. 네임스페이스에 항목이 많을수록 충돌 위험이 커지므로 사람들은 다른 네임스페이스보다 (해당 네임스페이스에 있는 항목의 수로 인해) std
궁극적으로 이것은 쓰기 가능성과 신뢰성/유지보수 가능성 사이의 절충점입니다. 가독성도 요인이 될 수 있지만 어느 쪽이든 이에 대한 주장을 볼 수 있습니다. 일반적으로 안정성과 유지 관리 가능성이 더 중요하다고 말하지만 이 경우 상당히 드문 신뢰성/유지 관리 가능성에 대한 쓰기 가능성 비용을 지속적으로 지불하게 됩니다. '최상의' 절충안이 프로젝트와 우선순위를 결정합니다.
동시에 여러 네임 스페이스를 사용하는 것은 분명 재앙이지만, 그냥 네임 스페이스를 사용하여 std
만 네임 스페이스 std
내 의견에 거래 큰이 재정은 자신의 코드에 의해 발생할 수 있기 때문 아니다 ...
따라서 "int" 또는 "class"와 같은 예약된 이름으로 기능을 고려하면 됩니다.
사람들은 그것에 대해 너무 항문적인 것을 멈춰야 합니다. 당신의 선생님은 항상 옳았습니다. 하나의 네임스페이스만 사용하세요. 그것이 네임스페이스를 사용하는 요점입니다. 동시에 하나 이상을 사용해서는 안됩니다. 그것이 당신 자신의 것이 아니라면. 다시 말하지만 재정의는 일어나지 않을 것입니다.
당신과 다른 스타일과 모범 사례 의견을 가진 사람들이 작성한 코드를 읽을 수 있어야 합니다.
cout
만 사용하는 경우 아무도 혼동하지 않습니다. 그러나 많은 네임스페이스가 날아다니고 이 클래스를 보고 정확히 무엇을 하는지 확실하지 않은 경우 명시적 네임스페이스를 갖는 것은 일종의 주석 역할을 합니다. 언뜻 보면 "오, 이것은 파일 시스템 작업입니다" 또는 "네트워크 작업을 하고 있습니다"라는 것을 알 수 있습니다.
다른 의견에 동의하지만 가독성에 관한 문제를 해결하고 싶습니다. 파일, 함수 또는 클래스 선언의 맨 위에 typedef를 사용하면 이 모든 것을 피할 수 있습니다.
클래스의 메소드가 유사한 데이터 유형(멤버)을 처리하는 경향이 있고 typedef는 클래스 컨텍스트에서 의미 있는 이름을 할당할 수 있는 기회이기 때문에 일반적으로 클래스 선언에서 사용합니다. 이것은 실제로 클래스 메소드의 정의에서 가독성을 돕습니다.
// Header class File { typedef std::vector<std::string> Lines; Lines ReadLines(); }
그리고 구현에서:
// .cpp Lines File::ReadLines() { Lines lines; // Get them... return lines; }
반대로:
// .cpp vector<string> File::ReadLines() { vector<string> lines; // Get them... return lines; }
또는:
// .cpp std::vector<std::string> File::ReadLines() { std::vector<std::string> lines; // Get them... return lines; }
네임스페이스는 명명된 범위입니다. 네임스페이스는 관련 선언을 그룹화하고 별도의 항목을 별도로 유지하는 데 사용됩니다. 예를 들어, 별도로 개발된 두 라이브러리는 동일한 이름을 사용하여 다른 항목을 참조할 수 있지만 사용자는 여전히 둘 다 사용할 수 있습니다.
namespace Mylib{ template<class T> class Stack{ /* ... */ }; // ... } namespace Yourlib{ class Stack{ /* ... */ }; // ... } void f(int max) { Mylib::Stack<int> s1(max); // Use my stack Yourlib::Stack s2(max); // Use your stack // ... }
네임스페이스 이름을 반복하는 것은 독자와 작성자 모두에게 주의를 산만하게 할 수 있습니다. 결과적으로 특정 네임스페이스의 이름을 명시적 자격 없이 사용할 수 있다고 말할 수 있습니다. 예를 들어:
void f(int max) { using namespace Mylib; // Make names from Mylib accessible Stack<int> s1(max); // Use my stack Yourlib::Stack s2(max); // Use your stack // ... }
네임스페이스는 다양한 라이브러리와 코드 버전을 관리하기 위한 강력한 도구를 제공합니다. 특히, 비로컬 이름에 대한 참조를 명시적으로 만드는 방법에 대한 프로그래머 대안을 제공합니다.
출처: Bjarne Stroustrup 의 C++ 프로그래밍 언어 개요
using namespace std
하면 알고리즘 라이브러리의 함수이기도 한 count의 모호성으로 인해 컴파일 오류가 발생하는 예입니다.
#include <iostream> #include <algorithm> using namespace std; int count = 1; int main() { cout << count << endl; }
소프트웨어나 프로젝트 성능을 악화시키지 않습니다. 소스 코드의 시작 부분에 네임스페이스를 포함하는 것은 나쁘지 않습니다. using namespace std
명령의 포함은 필요와 소프트웨어 또는 프로젝트를 개발하는 방식에 따라 다릅니다.
namespace std
에는 C++ 표준 함수와 변수가 포함되어 있습니다. 이 네임스페이스는 C++ 표준 함수를 자주 사용할 때 유용합니다.
이 페이지 에서 언급한 바와 같이:
네임스페이스 std를 사용하는 문은 일반적으로 나쁜 습관으로 간주됩니다. 이 명령문의 대안은 유형을 선언할 때마다 범위 operator(::)를 사용하여 식별자가 속한 네임스페이스를 지정하는 것입니다.
그리고 이 의견을 보십시오 :
네임스페이스를 많이 사용하고 충돌할 것이 없다는 것을 확신할 때 소스 파일에서 "using namespace std"를 사용하는 데 문제가 없습니다.
어떤 사람들은 네임스페이스에서 모든 함수와 변수를 호출하기 때문에 소스 파일에 using namespace std
를 포함하는 것은 좋지 않다고 말했습니다. namespace std
포함된 다른 함수와 동일한 이름으로 새 함수를 정의하려는 경우 함수를 오버로드하고 컴파일 또는 실행으로 인해 문제가 발생할 수 있습니다. 예상대로 컴파일되거나 실행되지 않습니다.
이 페이지 에서 언급한 바와 같이:
이 명령문이 std::를 입력하지 않아도 되지만 std 네임스페이스에 정의된 클래스나 유형에 액세스하려고 할 때마다 std 네임스페이스 전체를 프로그램의 현재 네임스페이스로 가져옵니다. 이것이 왜 그렇게 좋지 않은지 이해하기 위해 몇 가지 예를 들어 보겠습니다.
...
이제 개발의 나중 단계에서 "foo"(예를 들어)라는 라이브러리에서 사용자 정의 구현된 다른 버전의 cout을 사용하려고 합니다.
...
cout이 가리키는 라이브러리가 어떻게 모호한지 알 수 있습니까? 컴파일러는 이를 감지하고 프로그램을 컴파일하지 않을 수 있습니다. 최악의 경우, 프로그램은 여전히 컴파일되지만 식별자가 속한 네임스페이스를 지정하지 않았기 때문에 잘못된 함수를 호출할 수 있습니다.
케이스 바이 케이스입니다. 우리는 소프트웨어의 수명 기간 동안 "총 소유 비용"을 최소화하고자 합니다. "using namespace std"라고 명시하면 약간의 비용이 발생하지만 사용하지 않으면 가독성에도 문제가 있습니다.
사람들은 그것을 사용할 때 표준 라이브러리가 새로운 기호와 정의를 도입할 때 코드 컴파일이 중단되고 변수 이름을 강제로 바꿀 수 있다는 점을 정확하게 지적합니다. 그러나 이것은 아마도 장기적으로 좋은 방법일 것입니다. 왜냐하면 당신이 어떤 놀라운 목적을 위해 키워드를 사용한다면 미래의 유지 관리자는 순간적으로 혼란스럽거나 주의가 산만해질 것이기 때문입니다.
다른 모든 사람이 알고 있는 벡터가 아닌 벡터라는 템플릿을 원하지 않습니다. 그리고 C++ 라이브러리에 도입된 새로운 정의의 수는 너무 적어서 나오지 않을 수도 있습니다. 이 변화의 이런 종류의 작업을 수행하는 데에 비용이 있지만, 비용이 높은되지 않고 사용하지 않음으로써 얻을 수있는 선명도에 의해 상쇄되는 std
다른 목적을위한 심볼 이름을.
클래스, 변수 및 함수의 수를 감안할 때 std::
를 모두 지정하면 코드가 50% 이상 부풀려져 머리를 이해하기가 더 어려워질 수 있습니다. 한 화면의 코드에서 사용할 수 있는 알고리즘 또는 메서드의 단계는 이제 앞뒤로 스크롤하여 따라야 합니다. 이것은 실제 비용입니다. 틀림없이 그것은 높은 비용이 아닐 수 있지만, 존재조차 부정하는 사람들은 경험이 없거나 독단적이거나 단순히 잘못된 것입니다.
다음 규칙을 제안합니다.
std
는 다른 모든 라이브러리와 다릅니다. 그것은 모든 사람이 기본적으로 알아야 하는 하나의 라이브러리이며, 제 생각에는 언어의 일부로 생각하는 것이 가장 좋습니다. 일반적으로 다른 라이브러리가 없는 경우에도 using namespace std
를 사용하는 훌륭한 사례가 있습니다.
헤더 using
컴파일 단위(.cpp 파일)의 작성자에게 결정을 강요하지 마십시오. 항상 컴파일 단위 작성자에게 결정을 미루십시오. using namespace std
를 사용하기로 결정한 프로젝트에서도 해당 규칙에 대한 예외로 가장 잘 처리되는 몇 가지 모듈에 벌금을 부과할 수 있습니다.
네임스페이스 기능을 사용하면 심볼이 동일하게 정의된 많은 모듈을 가질 수 있지만 그렇게 하는 것은 혼란스러울 것입니다. 가능한 한 다른 이름을 유지하십시오. 네임스페이스 기능을 사용하지 않더라도 foo
라는 클래스가 있고 std
foo
라는 클래스를 도입한다면 어쨌든 클래스의 이름을 바꾸는 것이 장기적으로 더 나을 것입니다.
네임스페이스 사용에 대한 대안은 기호를 접두사로 수동으로 네임스페이스 기호를 사용하는 것입니다. 수십 년 동안 사용한 두 개의 라이브러리가 있습니다. 둘 다 C 라이브러리로 시작합니다. 실제로 모든 기호에는 "AK" 또는 "SCWin" 접두사가 붙습니다. 일반적으로 이것은 "using" 구문을 피하는 것과 같지만 쌍 콜론을 작성하지 않습니다. AK::foo()
는 대신 AKFoo()
입니다. 그것은 코드를 5-10% 더 조밀하고 덜 장황하게 만들고, 유일한 단점은 동일한 접두사를 가진 두 개의 라이브러리를 사용해야 하는 경우 큰 문제가 발생한다는 것입니다. X Window 라이브러리는 몇 가지 #define을 사용하여 수행하는 것을 잊었다는 점을 제외하고는 이와 관련하여 탁월합니다. TRUE 및 FALSE는 XTRUE 및 XFALSE여야 하며, 이는 마찬가지로 TRUE 및 FALSE를 사용하는 Sybase 또는 Oracle과 네임스페이스 충돌을 설정합니다. 다른 가치로! (데이터베이스의 경우 ASCII 0과 1!) 이것의 특별한 이점 중 하나는 전처리기 정의에 겉으로 보기에 무색하게 적용되는 반면 / namespace
using
하는 C++에서는 처리하지 않는다는 것입니다. 이것의 좋은 이점은 프로젝트의 일부에서 궁극적으로 도서관이 되는 유기적인 경사를 제공한다는 것입니다. 내 대규모 응용 프로그램에서 모든 창 클래스는 접두사 Win
, 모든 신호 처리 모듈 Mod 등입니다. 이들 중 어느 것도 재사용할 가능성이 거의 없으므로 각 그룹을 라이브러리로 만드는 실질적인 이점은 없지만 프로젝트가 어떻게 하위 프로젝트로 분할되는지는 몇 초 만에 명확해집니다.
나는 다른 사람들의 의견에 동의합니다. 이름 충돌, 모호성을 요구하고 있으며 사실은 덜 명시적입니다. 나는의 사용을 볼 수 있지만 using
, 내 개인적인 취향을 제한하는 것입니다. 나는 또한 다른 사람들이 지적한 것을 강력하게 고려할 것입니다.
상당히 일반적인 이름일 수 있는 함수 이름을 찾고 싶지만 std
std
네임스페이스, X
네임스페이스, ..에 없는 모든 호출을 변경하고 싶습니다.) .) 그렇다면 이것을 제안하는 방법은 무엇입니까?
프로그램을 작성할 수는 있지만 프로젝트를 유지 관리하기 위해 프로그램을 작성하는 것보다 프로젝트 자체에 시간을 투자하는 것이 낫지 않을까요?
개인적으로, 나는 실제로 std::
접두사를 신경 쓰지 않습니다. 없는 것보다 외모가 마음에 든다. 그것이 명시적이어서 "이것은 내 코드가 아닙니다 ... 표준 라이브러리를 사용하고 있습니다"라고 말하거나 다른 무엇인지는 모르겠지만 그것이 더 좋아 보인다고 생각합니다. 내가 최근에 C++에 입문했다는 점을 고려할 때 이것은 이상할 수 있습니다.
위의 내용과 다른 분들이 지적한 내용과 다소 관련이 있지만 한 가지 더 있습니다. 이것은 나쁜 습관일 수 있지만 std::name
을 예약하고 프로그램별 구현을 위해 이름을 예약하는 경우가 있습니다. 예, 실제로 이것은 당신을 물고 당신을 심하게 물릴 수 있지만, 모든 것은 내가 이 프로젝트를 처음부터 시작했고 내가 이 프로젝트의 유일한 프로그래머라는 사실로 귀결됩니다. 예: std::string
string
이라고 부릅니다. 도움이 되는 추가 사항이 있습니다. 나는 소문자 이름을 선호하는 C 및 Unix(+ Linux) 경향 때문에 부분적으로 그렇게 했습니다.
그 외에도 네임스페이스 별칭을 가질 수 있습니다. 다음은 참조되지 않았을 수 있는 유용한 경우의 예입니다. 저는 C++11 표준을 사용하고 특히 libstdc++와 함께 사용합니다. 글쎄, 완전한 std::regex
지원이 없습니다. 물론 컴파일되지만 프로그래머 측에서 오류가 발생하는 라인을 따라 예외가 발생합니다. 하지만 실천이 부족하다.
그래서 제가 해결한 방법입니다. Boost의 정규식을 설치하고 연결합니다. 그런 다음 libstdc++에서 완전히 구현되었을 때 이 블록만 제거하면 코드가 동일하게 유지되도록 다음을 수행합니다.
namespace std { using boost::regex; using boost::regex_error; using boost::regex_replace; using boost::regex_search; using boost::regex_match; using boost::smatch; namespace regex_constants = boost::regex_constants; }
나는 그것이 나쁜 생각인지 아닌지에 대해 논쟁하지 않을 것입니다. 그러나 나는 그것이 내 프로젝트를 깨끗하게 유지하고 동시에 그것을 구체적으로 만든다고 주장할 것입니다. 사실, 나는 Boost를 사용해야 하지만 libstdc++가 결국 그것을 갖게 될 것처럼 그것을 사용하고 있습니다. 예, 자신의 프로젝트를 시작하고 처음에 표준(...)으로 시작하는 것은 유지 관리, 개발 및 프로젝트와 관련된 모든 것을 돕는 데 매우 먼 길을 가는 것입니다!
뭔가를 명확히하기 위해 : 실제로 STL 의 클래스 이름을 의도적으로, 더 구체적으로 대신 사용하는 것은 좋은 생각이 아니라고 생각합니다. 문자열은 '문자열'이라는 개념이 마음에 들지 않았기 때문에 예외입니다(여기서 첫 번째, 위 또는 두 번째는 무시해야 하는 경우 말장난).
현재로서는 여전히 C에 대해 매우 편향되어 있고 C++에 대해 편향되어 있습니다. 세부 사항을 아끼고, 내가 작업하는 대부분은 C에 더 적합합니다(그러나 그것은 좋은 연습이었고 나 자신을 만드는 좋은 방법이었습니다. 덜 폐쇄적이며 덜 오만하고 더 수용적입니다.) 내가 수행하는 경우 이름 충돌을 야기 두 가지 이름을 (같은 것) 종류 I 실제로 목록을 사용 않으며, (그것은 매우 일반적인하지가 있습니까?)하지만 유용한 것은 일부는 이미 제안 무엇 using namespace std;
, 그리고 그것을 위해 나는 표준 사용을 의도한다면 그것을 지정해야 할 것이라는 점을 알고 통제하고 구체적으로 말하는 것을 선호합니다. 간단히 말해서 가정이 허용되지 않습니다.
그리고 Boost의 정규식을 std
의 일부로 만드는 것입니다. 나는 미래의 통합을 위해 그렇게 하고 – 다시 말하지만 이것이 편견이라는 것을 완전히 인정합니다 – 나는 그것이 boost::regex:: ...
만큼 추악하다고 생각하지 않습니다. 사실, 그것은 나에게 또 다른 것입니다. C++에는 아직 외모와 메서드에서 완전히 받아들이지 못한 많은 것들이 있습니다(또 다른 예: 가변 템플릿 대 var 인수[가변 템플릿이 매우 유용하다는 것을 인정합니다!]). 내가 비록 그 것을 어렵게했다 동의, 나는 여전히 그들과 함께 문제가 있습니다.
cout
을 사용하는 라이브러리가 여러 개 있는 경우 다른 목적으로 잘못된 cout
사용할 수 있습니다.
예를 들어, using namespace std;
그리고 using namespace otherlib;
그냥 입력 cout
하기보다는, (둘 다 될 일이있는) std::cout
(또는 'otherlib::cout'
), 당신은 잘못 하나를 사용하고, 오류를 얻을 수 있습니다. std::cout
를 사용하는 것이 훨씬 더 효과적이고 효율적입니다.
모든 상황에서 반드시 나쁜 습관은 아니라고 생각하지만 사용하실 때 주의가 필요합니다. 라이브러리를 작성하는 경우 라이브러리가 다른 라이브러리와 충돌하지 않도록 네임스페이스와 함께 범위 확인 연산자를 사용해야 합니다. 응용 프로그램 수준 코드의 경우 문제가 없습니다.
정규화되지 않은 가져온 식별자를 사용하면 식별자가 선언된 위치를 찾기 위해 grep과 같은 외부 검색 도구가 필요합니다. 이것은 프로그램 정확성에 대한 추론을 어렵게 만듭니다.
위치에 따라 다릅니다. 공통 헤더인 경우 전역 네임스페이스에 병합하여 네임스페이스의 값을 줄이는 것입니다. 이것은 모듈을 전역으로 만드는 깔끔한 방법이 될 수 있음을 명심하십시오.
이는 종종 글로벌 네임스페이스 오염으로 알려진 나쁜 습관입니다. 둘 이상의 네임스페이스에 서명이 있는 동일한 함수 이름이 있는 경우 문제가 발생할 수 있습니다. 그러면 컴파일러가 어느 것을 호출할지 결정하는 것이 모호할 수 있으며 std::cout
. 도움이 되었기를 바랍니다. :)
"'namespace std를 사용하는' 이유는 무엇입니까? C++에서 나쁜 습관으로 간주됩니까?"
나는 그것을 다른 방식으로 표현합니다. 왜 일부 사람들은 5개의 추가 문자를 입력하는 것을 번거롭게 여길까요?
예를 들어 수치 소프트웨어를 작성하는 것을 고려하십시오. "벡터"가 문제 도메인의 가장 중요한 개념 중 하나인 경우 일반 "std::vector"를 "벡터"로 줄여 글로벌 네임스페이스를 오염시키는 것을 고려하는 이유는 무엇입니까?
출처 : http:www.stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
Java에서 String을 int로 어떻게 변환합니까? (0) | 2021.10.26 |
---|---|
jQuery에 "존재하는" 기능이 있습니까? (0) | 2021.10.09 |
참조로 변수를 전달하는 방법은 무엇입니까? (0) | 2021.10.09 |
객체가 배열인지 어떻게 확인할 수 있습니까? (0) | 2021.10.09 |
Git 리포지토리에서 삭제된 파일을 찾고 복원하는 방법 (0) | 2021.10.09 |