2016-12-12 1 views
2

큰 파일에 Constants.h 파일이 있는데 약 200 개의 변수 (대부분은 배열)가 선언되고 초기화됩니다. 네임 스페이스를 사용하고 있습니다.헤더 파일에 선언 및 초기화가 너무 많음 C++

METHOD 1

//Constants.h 

#ifndef CONSTANTS_H_ 
#define CONSTANTS_H_ 

namespace LibConstants 
{ 
    const int a = 12; 
    const std::string theme[2]; = {"themeA", "themeB"}; 
    const int arr[2] = {1, 2}; 
    // and around 200 more declarations with initialization 
} 
#endif 

.h이 파일은 거의 모든 .cpp 파일 만 아주 최소한의 변수 LibConstants::theme[0] 같이 사용중인 각 타임 #include이다.

내 방식은 정상적으로 작동하지만 불필요하게 메모리를 할당합니까? 접근 방식에 따라 .h 파일의 변수 만 정의하고 .cpp으로 초기화해야합니까? 아래 코드에서

처럼 : 방법 2 :

//Constants.h 

#ifndef CONSTANTS_H_ 
#define CONSTANTS_H_ 

namespace LibConstants { 

    std::string getMyTheme(int arg); 
    std::string getMyThemeName(int arg); 

    const int a; 
    const std::string theme[2]; 
    const int arr[2]; 
    // and around 200 more declarations with initialisation 
}; 
#endif 

처럼 사용 CPP 파일

//Constants.cpp 

#include LibConstants.h 
using namespace LibConstants { 
    std::string getMyTheme(int arg) { 
     theme[2] = {"themeA", "themeB"}; 
     return theme[arg]; 
    } 
    std::string getMyThemeName(int arg) { 
     ... 
    } 
} 

에서 초기화 중

여기서 헤더 파일에 const std::string st[2];으로 선언 된 배열을 제외하고 불필요한 변수에 대한 불필요한 메모리 할당은 발생하지 않습니다.

여기서 "arg = 0"은 런타임 관련입니다. 일부 변수가 런타임에 종속적이지 않고 컴파일 시간 만 종속적 인 경우 중요합니까? 해당 경우 .cpp 파일의 자리 표시 자 값을 간단히 바꿉니다.

내가 잘못하면 어디든지 수정하십시오.

+0

컴파일 타임 상수는 헤더 또는 소스 파일에서 선언하고 초기화하는지 여부에 관계없이 대부분의 구현에서 데이터 세그먼트로 이동합니다. 예를 들어'int a [] = {/ * 큰 배열 * /}'이라고 가정 해 봅시다. 'a'는 상수가 아니지만 초기화 된 파일은 여전히 ​​어딘가에 있어야하며 프로그램은 여전히 ​​그것을로드해야합니다. 그래서이 경우 나는 그것이 물질적 인 차이를 만든다고 생각하지 않는다. 반면에, 변수가 생성자 또는 다른 방법으로 런타임 실행을 초기화해야하는 경우. 함수에서 랩핑하고 필요에 따라 작성하는 것이 좋습니다. –

+0

@ YanZhou 빠른 답장을 보내 주셔서 감사합니다. 위의 두 메서드는 모두 컴파일 시간이 있고 메모리를 사용하지 않지만 각 .cpp 파일의 자리 표시 자만 바꿉니다. – myDoggyWritesCode

+0

아니오 잠시 답을 작성하십시오. –

답변

2

std::string 예를 들어보세요. 그것은에만 적용

namespace Constants { 
const std::string str = "A not very short string"; 
} 

str

는이 생성자가, 클래스 타입이며, 짧은 문자열의 최적화에도 그 경우. 구현에 사용되지 않는 (내용을 저장하기 위해 메모리를 할당 할 수있다, 고려 ~, "짧은 문자열"). 네임 스페이스 범위 변수로 선언됩니다. 따라서 프로그램은 출시 될 때이 변수를 구성해야합니다. 이 변수가 선언 된 모든 프로그램은 메모리를 할당하고 내용을 초기화해야합니다. 그것은 당신의 성능에 영향을 미칠 정도에 따라 아마도 원하지 않는 오버 헤드 일 것입니다. 한편

, 당신이있는 경우,

const std::string &str() 
{ 
    const static std::string s = "A not very short string"; 

    return s; 
} 

지금, 당신은 정적 지역 변수를 가지고있다. 이 함수는 함수의 첫 번째 항목에서 초기화됩니다. 그리고 그것은 한 번만 초기화 될 것입니다. str이 호출되지 않으면 초기화되지 않습니다.

그러나 리터럴 문자열 "A not very short string"은 여전히 ​​일부 메모리를 차지할 것입니다. 저장 위치 및 저장 방법은 구현 정의됩니다. 일반적으로 데이터 세그먼트에 영향을 미치지는 않습니다.

클래스 유형과 대조됩니다. 기본 유형, 특히 헤더에 정수 유형을 정의하는 것이 바람직합니다. 예를 들어

,

namespace Constants { 
constexpr int x = 10; 
} 

좋은 최적화 컴파일러는 가장 가능성이 전혀 변수 x와 그 내용 10를 저장하지 않습니다. 대신, x이 사용 된 곳이면 10으로 대체되며 경우에 따라 명령어 op-code (즉각 피연산자)로 코딩됩니다. 물론 이것은 다시 구현 세부 사항입니다. 그리고 이러한 최적화는 모든 컴파일러에 의존 할 수 없습니다. x의 주소를 사용하거나 다른 ODR을 사용하면 컴파일러는이 변수에 대한 여유 공간을 만들어야합니다. 그러나 최하위 라인은 외부 소스 파일에서이 상수를 정의하는 것보다 헤더에서이 상수를 선언하는 것이 나빠질 것 같지 않습니다.

+0

변수 선언을위한 정수 타입을 정의하는 것이 바람직한 이유는 무엇입니까? – myDoggyWritesCode

+0

정확하게 이해했는지 확인하십시오. 또한, 그것은 내 질문의 마지막에 내가 쓴 것을 설명 할 것이다. 네, 최적화 컴파일러는 변수 x와 값 10을 저장하지 않습니다.이 경우 실행 시간 관련이 없기 때문입니다. 하지만 논리 계산/로컬 저장소에서 인수를 얻는 경우에는 런타임 관련이있는 경우에는 함수를 통해 얻는 것이 좋습니다. 함수를 통해, 나는 당신의 방법 const std :: string & str() 또는 나의 방법 2를 의미한다. 나는 맞습니까? 그렇다면, 내 파일의 대부분의 변수가 런타임 로직을 필요로하기 때문에 방법 2를 따르는 것이 좋습니다. – myDoggyWritesCode

+1

@ user3241111 소스 파일에 정수 변수를 저장하면 컴파일러가 일부 최적화를 수행하지 못하도록 메모리 저장 공간이 거의 필요하지 않습니다. 예를 들어, 적분이 나중에 루프 카운트로 사용된다고 가정하십시오. 컴파일러가 헤더에서이를보고 루프가 작다는 것을 확인하면 효과적으로 루프를 풀 수 있습니다. 그러나 선언 만하고 소스 파일에 정의하면 컴파일러는이를 수행 할 수 없습니다. 두 번째 설명에 대한 대답은 '예'입니다. 핵심은 전역 변수와 네임 스페이스 범위 변수가 나중에 사용되는지 여부에 관계없이 초기화되어야한다는 것을 기억하는 것입니다. –