2012-04-21 11 views
4

, 나는 정의하려면 몇 가지 로컬이 아닌 다른 클래스, 함수, 파일, 내가 알고 접근 방법에서 사용할 수있는 const를 문자열 :은 static const string 멤버 변수로 사용하기 전에 항상 초기화됩니까? C++에서

  1. 사용 지침을 정의, 예를 들어,

    #define STR_VALUE "some_string_value" 
    
  2. const 클래스 멤버 변수

    class Demo { 
    public: 
        static const std::string ConstStrVal; 
    }; 
    // then in cpp 
    std::string Demo::ConstStrVal = "some_string_value"; 
    
  3. const 클래스 멤버 함수. 우리는 두번째 방법을 사용하는 경우가 실제로 어떤 경우에 어떤 코드를 사용하기 전에

    class Demo{ 
    public: 
        static const std::string GetValue(){return "some_string_value";} 
    }; 
    

지금 무엇을 나는 확실하지 오전, 변수 ConstStrVal는 항상 "some_string_value"로 초기화된다? 나는 "static initialization order fiasco" 때문에 이것을 염려합니다. 이 문제가 타당하다면 왜 2 번 접근법을 사용하고 있습니까?

2 또는 3 중 어느 것이 가장 좋습니다. #define 지시어에는 범위에 대한 존중이 없으므로 대부분의 사람들은 범위를 추천하지 않습니다.

감사합니다.

답변

4

변수 ConstStrVal 항상 초기화 어쨌든 어떤 코드에서 실제로 사용되기 전에 "some_string_value"로?

없음 그것으로 초기화있어 가치 및 초기화의 순서에 따라

.하지 ConstStrVal에는 전역 생성자가 있습니다.

생성자와 다른 전역 객체를 추가 고려 :

static const std::string ConstStrVal2(ConstStrVal); 

순서는 언어에 의해 정의되지 않으며, ConstStrVal가 구축되기 전에 ConstStrVal2의 생성자를 호출 할 수 있습니다.

초기화 순서는 여러 가지 이유로 달라질 수 있지만 종종 툴체인에 의해 지정됩니다. 링크 된 오브젝트 파일의 순서를 변경하면 (예를 들어) 이미지의 초기화 순서를 변경할 수 있고 오류가 발생합니다.

왜 모두 접근 방식을 사용하고 있습니까?

많은 사람들이 ... 아주 좋은 이유로 다른 방법을 사용

가장 좋은 방법입니다

, 2 또는 3?

번호 3. 또한과 같이 여러 구조물을 방지 할 수 있습니다

class Demo { 
public: 
    static const std::string& GetValue() { 
    // this is constructed exactly once, when the function is first called 
    static const std::string s("some_string_value"); 
    return s; 
    } 
}; 

주의 :이 방법 여전히 ConstStrVal2(ConstStrVal)에서 볼 초기화 문제 할 수 있습니다. 그러나 초기화 순서에 대해 더 많은 제어권을 가지며 전역 생성자가있는 객체와 비교할 때 이식성있게 해결하는 것이 더 쉬운 문제입니다.

+1

나는이 대답을 좋아한다. 내가 이해할 수없는 한 가지는, 스택 오버플로에서의 대답을 잠시 동안 찾았습니다. 대부분의 사람들은 접근 방식 2를 언급하지만, 거의 접근하지 않습니다. – Hunter

+0

@Hunter 이름은 "처음 사용할 때의 구조"입니다. 그 희망을 연구하면 도움이됩니다. – justin

1

일반적으로 I (및 많은 다른 사람들)는 함수가 변수가 아닌 값을 반환하는 것을 선호합니다. 함수가 향후 향상을 위해 더 큰 유연성을 제공하기 때문입니다. 성공적인 소프트웨어 프로젝트에 소비 된 대부분의 시간은 코드를 유지하고 향상시키는 것이며, 처음부터 작성하는 것이 아님을 기억하십시오. 오늘의 상수가 내일 컴파일 시간 상수가 아닐지 예측하는 것은 어렵습니다. 어쩌면 언젠가는 설정 파일에서 읽을 수있을 것입니다.

그래서 나는 현재 원하는 것을 수행하고 미래에 더 많은 유연성을 제공하기 때문에 접근법 3을 권장합니다.

+0

+1하지만 여전히 더 어둡습니다. – enobayram

0

C++에서 전처리기를 사용하지 마십시오. 또한, 왜 당신은 클래스에서 문자열을 가질 것이지만 다른 클래스에서는 그것을 필요로할까요? 더 나은 캡슐화를 위해 클래스 디자인을 다시 평가할 것입니다. 당신이 절대적으로이 전역 문자열이 필요하면 그때는 globals.h/CPP 모듈을 추가하는 것을 고려 것이다 다음 선언/거기 문자열을 정의 : 우리는 두번째 방법을 사용하는 경우

const char* const kMyErrorMsg = "This is my error message!"; 
+0

전역 범위에서 const 문자열을 던지는 것이 좋습니다. 범위가 지정된 const는 네임 스페이스 또는 클래스 여야합니다. 이 경우 클래스는 전역 공간을 오염시키지 않도록 범위에서 문자열을 제한하는 방법이지만 필요로하는 사용자가 액세스 할 수 있도록하는 것이 목적입니다. – Hunter

+0

예, 가능한 경우 범위를 제한하는 것이 좋습니다. 의미는 특정 클래스 내에 문자열을 저장하는 것이 타당합니다. 나는 그것이 당신이 무엇을하려고하는지, 어떤 클래스를 고집하고 있는지에 달려 있다고 생각한다. 또한, C 문자열을 사용하기 위해 문자열 객체가 필요 없다. – keelerjr12

+0

왜 우리는 정적 멤버 변수/함수를 사용하므로 객체 생성자 오버 헤드가 없습니다. 하나의 클래스에서 모든 종류의 오류 메시지를 정의하고 다른 10 개의 클래스가 메시지를 사용하도록하지만 900 개의 나머지 클래스가 메시지를 알고 싶지 않은 경우 어떻게해야합니까? – Hunter

0

다른 방법으로 성취 할 수없는 거룩한 목적을 달성하지 못한다면 C++에서 전 처리기 지시문을 사용하지 마십시오. 표준 (3.6.2)에서

정적 저장 기간 (3.7.1)와

개체는 다른 초기화가 이루어진다 (8.5) 전에 제로 - 초기화되어야한다. 정적 저장 기간 및 정적 저장소가있는 POD 유형의 개체 지속 시간은 상수 식 (5.19)으로 초기화 할 수 있습니다. 이것은 상수 초기화라고하는 입니다. 함께 zero-initialization과 상수 초기화를 정적 초기화라고 부릅니다. 다른 모든 초기화는 동적 초기화입니다. 동적 초기화가 일어나기 전에 정적 초기화를 수행해야합니다. 동적 개체의 초기화 또는 순서가 지정되지 않았습니다. 명시 적으로 특수화 된 클래스 템플릿 정적 데이터의 정의 멤버가 초기화를 명령했습니다. 다른 클래스 템플릿 정적 데이터 멤버 (즉, 암시 적으로 또는 명시 적으로 인스턴스화 된 특수화) 은 순서가 지정되어 있지 않습니다. 네임 스페이스 범위에 정의 된 다른 개체는 초기화 순서가 지정됩니다. 하나의 번역 단위 내에 정의 된 객체와 초기화 된 객체는 번역 단위에서 정의 된 순서대로 으로 초기화되어야한다. 초기화 순서는 정렬되지 않은 초기화 오브젝트와 다른 변환 단위로 정의 된 오브젝트에 대해서는 지정되지 않습니다.

따라서 2의 운명은 변수가 정적 초기화인지 또는 동적 초기화인지에 따라 다릅니다. 예를 들어, 구체적인 예를 들어, const char * Demo::ConstStrVal = "some_string_value"; (값이 프로그램에서 일정하게 유지되는 경우 더 좋은 경우 const char Demo::ConstStrVal[])을 사용하면 무엇이든지 상관없이 초기화된다는 것을 확신 할 수 있습니다. std::string을 사용하면 POD 유형이 아니기 때문에 확신 할 수 없습니다 (이 경우 확실하지는 않지만 확실합니다).

세 번째 방법을 사용하면 확실한 결과를 얻을 수 있으며 저스틴의 대답은 불필요한 구조가 없음을 의미합니다.정적 메서드에는 변수가 이미 모든 호출에서 초기화되었는지 여부를 확인하는 숨겨진 오버 헤드가 있습니다. 간단한 상수를 반환하는 경우 함수가 아마 인라인 될 것이기 때문에 값을 반환하는 것이 확실히 빠릅니다.

모든 것이 정적 초기화에 의존하지 않도록 프로그램을 작성하십시오. 정적 변수는 편리함으로 가장 잘 간주되며, 초기화 명령을 저글링해야 할 때 더 이상 편리하지 않습니다.

+0

표준 문서는 항상 명확하고 도움이됩니다! 고마워요! 당신과 정의 둘 다 좋은 대답입니다. – Hunter