문제

의 기능은 C++를 만들 수 있는 능력 익명(anonymous)네임스페이스,그래서 다음과 같:

namespace {
    int cannotAccessOutsideThisFile() { ... }
} // namespace

당신이 생각하는 것은 쓸모없는--할 수 있기 때문에 없는 이름을 지정 네임스페이스는 불가능에 액세스 내에서 아무것도 그것을 의미합니다.그러나 이름 없는 네임스페이스 에서 액세스할 수 있는 파일들에서 만든 경우와 같이 암시적용 절니다.

나의 질문은 이유 때 또는 이에 좋을 것을 사용하여 정적 기능을 가지고 있는가?또는 그들은 기본적으로 두 가지 방법을 정확히 같은 것은?

도움이 되었습니까?

해결책

C ++ 표준은 섹션 7.3.1.1 이름없는 네임 스페이스, 2 항에서 읽습니다.

정적 키워드의 사용은 네임 스페이스 범위에서 객체를 선언 할 때 더 이상 사용되지 않으며, 이름이없는 Namespace는 우수한 대안을 제공합니다.

정적은 선언을 입력하지 않고 객체, 기능 및 익명 노조의 이름에만 적용됩니다.

편집하다:

정적 키워드의 이러한 사용을 가득 채우기로 결정한 결정 (변환 단위에서 변수 선언의 가시성에 영향을 미치기)이 역전되었습니다 (심판). 이 경우 정적 또는 이름없는 네임 스페이스를 사용하는 것은 본질적으로 똑같은 일을하는 두 가지 방법으로 돌아갑니다. 자세한 내용은 참조하십시오 이것 그래서 질문.

이름이없는 네임 스페이스는 여전히 번역 단위-로컬 유형을 정의 할 수있는 이점이 있습니다. 참조하십시오 이것 자세한 내용은 질문하십시오.

크레딧이 간다 마이크 퍼시 이것을 내 관심을 끌기 위해.

다른 팁

익명 네임 스페이스에 방법을 넣으면 우연히 하나의 정의 규칙, 당신이 링크 할 수있는 다른 방법과 동일하게 헬퍼 방법을 명명하는 것에 대해 걱정할 수 없도록합니다.

그리고 루크가 지적한 바와 같이, 익명 네임 스페이스는 정적 멤버보다 표준에 의해 선호됩니다.

Static이 놀라운 효과가있는 가장자리 케이스가 하나 있습니다 (적어도 나에게 그랬습니다). 14.6.4.2/1의 C ++ 03 표준 상태 :

함수 이름이 자격이없는 ID 그러나 아닙니다 템플릿 -ID, 후보 기능은 다음을 제외하고 일반적인 조회 규칙 (3.4.1, 3.4.2)을 사용하여 발견됩니다.

  • 자격이없는 이름 조회 (3.4.1)를 사용하는 조회의 일부의 경우 템플릿 정의 컨텍스트에서 외부 연결이있는 함수 선언 만 발견됩니다.
  • 관련 네임 스페이스 (3.4.2)를 사용하는 조회 부분의 경우 템플릿 정의 컨텍스트 또는 템플릿 인스턴스티션 컨텍스트에있는 외부 연결이있는 함수 선언 만 발견됩니다.

...

아래 코드는 호출됩니다 foo(void*) 그리고 아닙니다 foo(S const &) 당신이 기대할 수 있듯이.

template <typename T>
int b1 (T const & t)
{
  foo(t);
}

namespace NS
{
  namespace
  {
    struct S
    {
    public:
      operator void * () const;
    };

    void foo (void*);
    static void foo (S const &);   // Not considered 14.6.4.2(b1)
  }

}

void b2()
{
  NS::S s;
  b1 (s);
}

그 자체로 이것은 아마도 그렇게 큰 거래는 아니지만 완전히 준수하는 C ++ 컴파일러 (즉, 지원을받는 것)를 강조합니다. export) static 키워드에는 여전히 다른 방법으로 사용할 수없는 기능이 있습니다.

// bar.h
export template <typename T>
int b1 (T const & t);

// bar.cc
#include "bar.h"
template <typename T>
int b1 (T const & t)
{
  foo(t);
}

// foo.cc
#include "bar.h"
namespace NS
{
  namespace
  {
    struct S
    {
    };

    void foo (S const & s);  // Will be found by different TU 'bar.cc'
  }
}

void b2()
{
  NS::S s;
  b1 (s);
}

이름없는 네임 스페이스의 기능이 ADL을 사용하는 템플릿에서 찾을 수없는 유일한 방법은 static.

최신 C ++에 대한 업데이트

C ++ '11 기준으로, 이름없는 네임 스페이스의 구성원은 내부 연결을 암시 적으로 가지고 있습니다 (3.5/4).

이름이없는 네임 스페이스 또는 이름이없는 네임 스페이스 내에서 직접 또는 간접적으로 선언 된 네임 스페이스에는 내부 연결이 있습니다.

그러나 동시에, 14.6.4.2/1은 연결에 대한 언급을 제거하기 위해 업데이트되었습니다 (C ++ '14에서 가져온).

postfix-expression이 종속 이름 인 함수 호출의 경우, 후보 함수는 다음을 제외하고 일반적인 조회 규칙 (3.4.1, 3.4.2)을 사용하여 발견됩니다.

  • 자격이없는 이름 조회 (3.4.1)를 사용하는 조회의 일부의 경우 템플릿 정의 컨텍스트의 함수 선언 만 발견됩니다.

  • 관련 네임 스페이스 (3.4.2)를 사용하는 조회 부분의 경우 템플릿 정의 컨텍스트 또는 템플릿 인스턴스티션 컨텍스트에서 발견 된 함수 선언 만 발견됩니다.

결과적으로 정적 및 이름이없는 네임 스페이스 멤버 간의 이러한 특별한 차이는 더 이상 존재하지 않습니다.

최근에 정적 키워드를 코드의 익명 네임 스페이스로 교체하기 시작했지만 네임 스페이스의 변수가 더 이상 디버거에서 검사 할 수없는 문제가 발생했습니다. 나는 VC60을 사용하고 있었기 때문에 그것이 다른 디버거와의 문제가 아닌지 모르겠습니다. 내 해결 방법은 '모듈'네임 스페이스를 정의하는 것이 었습니다.

예를 들어, xmlutil.cpp 파일에서 모든 모듈 변수 및 함수에 대한 네임 스페이스 xmlutil_i {...}를 정의합니다. 이렇게하면 디버거에 xmlutil_i :: 자격을 적용하여 변수에 액세스 할 수 있습니다. 이 경우 '_i'는 다른 곳에서 사용할 수있는 xmlutil과 같은 공개 네임 스페이스와 구별됩니다.

진정한 익명의 것과 비교할 때이 접근법의 잠재적 단점은 다른 모듈에서 네임 스페이스 예선을 사용하여 원하는 정적 범위를 위반할 수 있다는 것입니다. 그래도 그것이 큰 관심사인지 모르겠습니다.

해당 목적으로 정적 키워드를 사용하는 것은 C ++ 98 표준에 의해 더 이상 사용되지 않습니다. Static의 문제점은 유형 정의에 적용되지 않는다는 것입니다. 또한 다른 상황에서 다양한 방식으로 사용되는 과부하 키워드이므로 이름이없는 네임 스페이스는 조금 단순화합니다.

경험을 통해 이전의 정적 기능을 익명 네임 스페이스에 넣는 것이 C ++ 방법이지만 이전 컴파일러는 때때로이 문제에 문제가있을 수 있습니다. 현재 대상 플랫폼을위한 몇 가지 컴파일러로 작업하고 있으며, 최신 Linux 컴파일러는 익명 네임 스페이스에 함수를 배치하는 데 적합합니다.

그러나 Solaris에서 실행되는 오래된 컴파일러는 지정되지 않은 미래의 릴리스까지 결혼을하면 때때로이를 받아들이고 다른 경우에는 오류로 표시됩니다. 오류는 나를 걱정하는 것이 아니라 그것이 무엇입니까? ~할 것 같다 그것을 할 때하고 있습니다 수락합니다 그것. 따라서 우리가 전반적으로 현대적으로 갈 때까지, 우리는 여전히 익명 네임 스페이스를 선호하는 정적 (일반적으로 클래스 스코핑 된) 기능을 사용하고 있습니다.

또한이 예제와 같은 변수에서 정적 키워드를 사용하는 경우.

namespace {
   static int flag;
}

매핑 파일에는 표시되지 않습니다

질문을 읽는 동안이 기능을 배운 후에는 추측 할 수 있습니다. 이것은 파일 레벨 정적 변수에 비해 몇 가지 장점을 제공하는 것 같습니다.

  • 익명의 네임 스페이스는 서로 안에 중첩 될 수 있으며, 상징이 탈출 할 수없는 여러 수준의 보호를 제공합니다.
  • 여러 익명 네임 스페이스를 동일한 소스 파일에 배치하여 실제로 동일한 파일 내에 다른 정적 레벨 스코프를 생성 할 수 있습니다.

누군가가 실제 코드에서 익명 네임 스페이스를 사용했다면 배우는 데 관심이 있습니다.

컴파일러 특정 사이에 차이 익명의 네임스페이스 및 정 기능을 볼 수 있는 컴파일을 다음과 같은 코드입니다.

#include <iostream>

namespace
{
    void unreferenced()
    {
        std::cout << "Unreferenced";
    }

    void referenced()
    {
        std::cout << "Referenced";
    }
}

static void static_unreferenced()
{
    std::cout << "Unreferenced";
}

static void static_referenced()
{
    std::cout << "Referenced";
}

int main()
{
    referenced();
    static_referenced();
    return 0;
}

컴파일드 대 2017(수준을 지정하는 4warning flag/W4 사용 경고 C4505:참조되지 않는 현지 기능이 제거되었습니다 다)및 gcc4.9 로-Wunused 능 또는 벽 플래그를 보여주는 대 2017 년만을 생산에 대한 경고를 사용하지 않는 정적 기능입니다.gcc4.9 고 높은뿐만 아니라,소 3.3 이상을 생산하는 것이에 대한 경고는 참조되지 않는 기능을 네임스페이스에서도에 대한 경고를 사용하지 않는 정적 기능입니다.

라이브 데모의 gcc4.9 및 MSVC2017

개인적으로 선호 정전기 방지 기능을 통한 이름 없는 네임스페이스는 다음과 같은 장점이 있습니다.

  • 그것은 분명하고 명확한 함수 정의에서 혼자는 개인의 번역 단위에 있는 그것의 컴파일합니다.와 namesless 네임스페이스 스크롤해야 할 수도 있습하고 검색하시는 경우는 기능에서는 네임스페이스가 있습니다.

  • 함수에서는 네임스페이스를 대상으로 외부에 의해 일(이상)컴파일러입니다.에 VS2017 그들은 여전히 extern.이러한 이유로는 경우에도 함수에서 이름이 없는 네임스페이스가 있는 여전히 표시하려는 그들에게 고정되어 있습니다.

  • 정전기 방지 기능을 작동하는 매우 비슷 C 또는 C++에서는 동안 무명의 네임스페이스가 분명히 C++니다.이름없는 네임스페이스 또한 추가 수준의 경우는 들여쓰기 그리고 난 다음과 같다:)

그래서 나는 행복하시는 것을 사용하여 정적 기능에 대한 지 않는 사용되지 않는 더 이상.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top