2011-03-20 2 views
7

내 프로그램의 다른 클래스에서 사용되는 많은 정적 함수가있는 도우미 클래스가 있습니다. 예 : C++의 정적 멤버 함수가 여러 번역 단위로 복사됩니까?

helper.h

:

Class helper { 
public: 
    static void fn1() 
    { /* defined in header itself */ } 

    /* fn2 defined in src file helper.cpp */ 
    static void fn2(); 
} 

도우미 정적 멤버 함수를 갖는다. 따라서 다른 모듈에서 도우미 객체를 만들지 않습니다. 도우미 기능과 같은 다른 모듈에 사용되는 :

A.cpp

#include "helper.h" 
A::foo() { 
    helper::fn1(); 
    helper::fn2(); 
} 

B.cpp

#include "helper.h" 
B::foo() { 
    helper::fn1(); 
    helper::fn2(); 
} 

컴파일러가 A.cppB.cpp에서 도우미 기능의 별도의 복사본을 만들 수 있습니까? 나는 몇몇 초기 게시물을 읽었고 컴파일러가 생성 할 응답들로부터 모았다. 그러나 fn1fn2의 주소를 printf("Address of fn1 is %p\n", &helper::fn1);printf("Address of fn1 is %p\n", &helper::fn1);으로 모두 A.cppB.cpp에서 인쇄하면 동일한 주소가 표시됩니다. 나는 지금 혼란 스럽다. 누군가가 뭔가를 놓친다면 분명히 해줄 수 있습니까?

헬퍼 함수의 여러 복사본이 생길 경우 (그럴 경우) 우리는 실행 가능한 크기를 줄이려고 노력하고 최적화하려고했습니다.

답변

8

클래스 본문 내에 정의 된 함수는 암시 적으로 inline으로 표시됩니다. 함수의 주소를 취하면 컴파일러는 (컴파일 단위당) 함수의 정규 복사본을 만들지 만 링커는 이러한 복사본 중 하나만 선택하여 실행 파일에 포함하므로 하나의 주소 만 있습니다.

그러나 인라인 프로세스는 컴파일 단위의 수를 초과하여 함수의 많은 복사본을 만들 수 있습니다. 종종 코드 복제의 증가 된 크기는 인수 전달 및 함수 호출 오버 헤드를 제거함으로써 공통적 인 하위 표현식 제거에 대한 기회뿐만 아니라 증가 된 최적화로 인해 상쇄됩니다. 인라인은 종종 크기와 속도 사이의 균형으로 간주되지만 크기가 증가합니다 종종 무시할 만하거나 부정적 일 수도 있습니다.

방금 ​​클래스에서 선언 된 다음 단일 컴파일 단위로 구현 된 함수는 확실히 실행 파일에 복사본이 하나만 있습니다.

+0

+1. 나는 조금 더주의 깊게 질문을 읽어야했다;) 내 지위를 삭제했다. – Mahesh

+0

@snkrish : 템플릿 정적 멤버 함수 또는 템플릿 정적 전역 함수입니까? 정적 멤버 함수 인 경우 템플릿 매개 변수의 각 조합에 대해 새 복사본을 얻지 만 컴파일 단위의 수는 여전히 영향을 미치지 않습니다. 정적 전역 (또는 네임 스페이스) 함수 인 경우 각 컴파일 단위에서 새 복사본을 가져옵니다. –

+0

자세한 답변을 주셔서 감사합니다. 이제 주소가 같은 이유를 알았습니다. 후속 질문이 있는데 별도의 게시물을 시작해야할지 모르겠습니다. 위의 fn2가 템플릿을 사용하여 작성된 경우 : template static void fn2(); - 헤더 자체에 fn2를 정의해야합니다. 또는 실행 파일 크기를 최적화하기 위해 extern 템플릿 helper :: fn2() {/ * helper.cpp * /} 정의 템플릿을 사용해야합니까? 컴파일러는 fn2가 정의 된 방법과 관계없이 다른 T로 호출 될 때마다 함수의 복사본을 만듭니다. – cppcoder

2

(예 : 클래스 선언에 정의 된 경우), 많은 컴파일러에서 암시 적으로 인라인으로 선언됩니다.

인라인 된 경우 일부 경우 복사되고 일부 경우 인라인되며 다른 경우에는 부분적으로 인라인 될 수 있습니다.

ODR (One Definition Rule)을 따르고 여러 번역에서 발견 된 사본은 링크 될 때 제거됩니다 (개인용 외부 인라인을 사용하도록 설정하지 않은 경우 실제로 내 보낸 구현이 중복 될 수 있음).

C : static은이 경우 고유 한 함수 복사본을 만들지 않습니다. 즉, 선언 한 클래스의 인스턴스없이 함수를 호출 할 수 있다는 의미입니다.

+0

고마워요 난 그냥 도우미 개체를 만들지 않고 fn1과 fn2를 호출하는 정적 사용하고 있습니다. – cppcoder

+0

@srikrish 알겠습니다. 왜냐하면 C 프로그래머는 링키지에 영향을 미치기 위해 정적으로 선언 된 함수에 익숙하기 때문에 (문제와 관련된 모든 알려진 사용법에 인라인되지 않을 때 개인용 사본을 생성 할 것입니다.) 그들에게 공통적 인 혼란의 원천이됩니다. 그 때문에, 그리고 나는 당신의 배경을 모르기 때문에 ... 나는 마지막 세부 사항을 추가했습니다. – justin

0

인라인 된 정적 클래스 방법은 인라인 된 자유 함수와 다르지 않습니다.이론적으로 ODR 규칙은 함수의 단일 인스턴스가 있음을 의미하지만 실제로 컴파일러는 항상 함수의 인스턴스 자체가 없도록 항상 인라인 할 수 있습니다.

그러나 의 아주 행위는 주소 함수의 인스턴스를 생성하는 컴파일러를 강제 함수의을 복용하고는 ODR을 시행 따라서 당신은 항상 얻을 수 있도록하는 편집 시스템의 문제 같은 주소.