태그 보관물: namespaces

namespaces

명명되지 않은 네임 스페이스가 사용되는 이유와 장점은 무엇입니까? 프로젝트는 이름없는 네임 스페이스를 자주

방금 새로운 C ++ 소프트웨어 프로젝트에 참여했으며 디자인을 이해하려고합니다. 이 프로젝트는 이름없는 네임 스페이스를 자주 사용합니다. 예를 들어, 클래스 정의 파일에서 다음과 같은 것이 발생할 수 있습니다.

// newusertype.cc
namespace {
  const int SIZE_OF_ARRAY_X;
  const int SIZE_OF_ARRAY_Y;
  bool getState(userType*,otherUserType*);
}

newusertype::newusertype(...) {...

명명되지 않은 네임 스페이스를 사용하게 만드는 디자인 고려 사항은 무엇입니까? 장점과 단점은 무엇입니까?



답변

명명되지 않은 네임 스페이스는 식별자 변환 단위를 로컬로 만드는 유틸리티입니다. 네임 스페이스에 대해 번역 단위당 고유 한 이름을 선택하는 것처럼 동작합니다.

namespace unique { /* empty */ }
using namespace unique;
namespace unique { /* namespace body. stuff in here */ }

빈 본문을 사용하는 추가 단계는 중요하므로 ::nameusing 지시문이 이미 수행되었으므로 네임 스페이스 본문 내 에서 해당 네임 스페이스에 정의 된 것과 같은 식별자를 참조 할 수 있습니다 .

help, 여러 번역 단위에 존재할 수있는 무료 기능 (예 🙂 을 가질 수 있으며 링크시 충돌하지 않습니다. 이 효과는 static식별자 선언에 넣을 수있는 C 에 사용 된 키워드 를 사용하는 것과 거의 동일합니다 . 명명되지 않은 네임 스페이스는 형식 변환 단위를 로컬로 만들 수도있는 탁월한 대안입니다.

namespace { int a1; }
static int a2;

모두 a의 지역 번역 단위이며, 링크시 충돌하지 않습니다. 그러나 a1익명 네임 스페이스의 고유 한 이름을 얻는다 는 점이 다릅니다 .

comeau-computing에서 훌륭한 기사를 읽으십시오. 왜 정적이 아닌 네임 스페이스가 사용됩니까? ( Archive.org 미러 ).


답변

익명 네임 스페이스에 무언가가 있다는 것은이 번역 단위 (.cpp 파일 및 모든 포함)에 대해 로컬 임을 의미합니다. 이는 동일한 이름을 가진 다른 기호가 다른 곳에 정의되어 있으면 ODR ( One Definition Rule)을 위반하지 않음을 의미합니다 .

이것은 정적 전역 변수 또는 정적 함수를 갖는 C 방식과 동일하지만 클래스 정의에도 사용할 수 있습니다 ( staticC ++ 대신 사용되어야 함 ).

동일한 파일의 모든 익명 네임 스페이스는 동일한 네임 스페이스로 취급되며 다른 파일의 모든 익명 네임 스페이스는 고유합니다. 익명 네임 스페이스는 다음과 같습니다.

namespace __unique_compiler_generated_identifer0x42 {
    ...
}
using namespace __unique_compiler_generated_identifer0x42;


답변

명명되지 않은 네임 스페이스는 클래스, 변수, 함수 및 객체가 정의 된 파일에 대한 액세스를 제한합니다. 명명되지 않은 네임 스페이스 기능은 staticC / C ++의 키워드 와 유사합니다 .
static키워드는 전역 변수 및 함수의 액세스가 정의 된 파일에 대한 액세스를 제한합니다. 명명되지 않은 네임 스페이스는 정적보다 유리하기 때문에
명명되지 않은 네임 스페이스와 static키워드 에는 차이가 있습니다 . static키워드는 변수, 함수 및 객체와 함께 사용할 수 있지만 사용자 정의 클래스에는 사용할 수 없습니다.
예를 들면 다음과 같습니다.

static int x;  // Correct 

그러나,

static class xyz {/*Body of class*/} //Wrong
static structure {/*Body of structure*/} //Wrong

그러나 명명되지 않은 네임 스페이스에서도 마찬가지입니다. 예를 들어

 namespace {
           class xyz {/*Body of class*/}
           static structure {/*Body of structure*/}
  } //Correct


답변

이 질문에 대한 다른 답변 외에도 익명 네임 스페이스를 사용하면 성능을 향상시킬 수 있습니다. 네임 스페이스 내의 심볼에는 외부 연결이 필요하지 않으므로 컴파일러는 네임 스페이스 내의 코드를 적극적으로 최적화 할 수 있습니다. 예를 들어, 루프에서 여러 번 호출되는 함수는 코드 크기에 영향을주지 않고 인라인 될 수 있습니다.

예를 들어, 내 시스템에서 익명 네임 스페이스가 사용되는 경우 다음 코드는 런타임의 약 70 %를 차지합니다 (x86-64 gcc-4.6.3 및 -O2; add_val의 추가 코드는 컴파일러가 포함시키지 않기를 바랍니다. 두 번).

#include <iostream>

namespace {
  double a;
  void b(double x)
  {
    a -= x;
  }
  void add_val(double x)
  {
    a += x;
    if(x==0.01) b(0);
    if(x==0.02) b(0.6);
    if(x==0.03) b(-0.1);
    if(x==0.04) b(0.4);
  }
}

int main()
{
  a = 0;
  for(int i=0; i<1000000000; ++i)
    {
      add_val(i*1e-10);
    }
  std::cout << a << '\n';
  return 0;
}


답변

이 예는 프로젝트에 참여한 사람들이 익명 네임 스페이스를 이해하지 못함을 보여줍니다. 🙂

namespace {
    const int SIZE_OF_ARRAY_X;
    const int SIZE_OF_ARRAY_Y;

const객체는 이미 정적 연결을 가지고 있으므로 다른 번역 단위에서 동일한 이름의 식별자와 충돌 할 수 없으므로 익명 네임 스페이스에있을 필요 는 없습니다.

    bool getState(userType*,otherUserType*);
}

그리고 이것은 실제로 비관입니다. getState()외부 연결이 있습니다. 일반적으로 정적 연결을 선호하는 것이 좋습니다. 심볼 테이블을 오염시키지 않기 때문입니다. 쓰는 것이 좋습니다

static bool getState(/*...*/);

여기. 나는 같은 함정에 빠졌다 (파일 이름은 익명 네임 스페이스를 선호하여 더 이상 사용되지 않는다고 제안하는 표준이 있지만 KDE와 같은 대형 C ++ 프로젝트에서 작업하면 많은 사람들이 머리를 바르게 돌린다. 다시 주위에 🙂


답변

익명 네임 스페이스는 동봉 된 변수, 함수, 클래스 등을 해당 파일 내에서만 사용할 수있게합니다. 귀하의 예에서 전역 변수를 피하는 방법입니다. 런타임 또는 컴파일 시간 성능 차이는 없습니다.

“이 변수, 함수, 클래스 등을 공개 또는 비공개로 설정하고 싶습니까?”외에도 많은 장점이나 단점이 없습니다.


답변