2010-01-25 3 views
1

나는 데이터를 사용하여 표준 변환하는 기능 ::지도를표준 : 맵 inizialitazion (한 번만)

struct HistoParameter 
{ 
    int nbins; 
    float first; 
    float last; 
    HistoParameter(int _nbins, int _first, int _last) : 
    nbins(_nbins), first(_first), last(_last) {}; 
}; 

HistoParameter* variable_to_parameter(char* var_name) 
{ 
    std::map<const std::string, HistoParameter*> hp; 
    hp[std::string("ph_pt")] = new HistoParameter(100,0,22000); 
    hp[std::string("ph_eta")] = new HistoParameter(100,-3,3); 
    // ... 
    return hp[var_name]; 
} 

내 구조체는 매우 가벼운이지만, 이미지가 무거운 될 수 있습니다. 이 함수는 내가이 함수를 호출 할 때마다 HistoParameter 객체를 많이 생성한다는 점에서 스위치 케이스가 더 효율적일 수 있다는 점이 중요합니다. 첫 번째 질문 : 나는 쓰레기를 만들고 있습니까?

두 번째 솔루션 :

bool first_time = true; 
HistoParameter* variable_to_parameter(char* var_name) 
{ 
    static std::map<const std::string, HistoParameter*> hp; 
    if (first_time) 
    { 
    hp[std::string("ph_pt")] = new HistoParameter(100,0,22000); 
    hp[std::string("ph_eta")] = new HistoParameter(100,-3,3); 
    // ... 
    } 
    first_time = false; 
    return hp[var_name]; 

은 괜찮습니다? 더 나은 솔루션?

답변

1

두 번째를 성병 : :지도 < 표준 : : 문자열, HistoParameter *> 회원을 가지고 할 것 솔루션은 확실히 효율성을 개선해야하지만 가능하면 최상의 구현이 (적어도 IMO는 아닙니다). 우선 variable_to_parameter 만 실제로 그것에 관심을 갖더라도 first_time을 공개적으로 볼 수 있습니다. 이미 hp을 함수에서 정적 변수로 만들었으며 first_time도 있어야합니다.

둘째, 나는 HistoParameter 값에 대해 포인터 및/또는 동적 할당을 사용하지 않을 것입니다. 하나의 int와 두 개의 float에는 단순히 그렇게 할 이유가 없습니다. 복사를하는 것이 너무 어려워지면 원시 포인터 대신 스마트 포인터 클래스를 사용하는 것이 더 나을 것입니다. 후자는 사용하기가 어려우며 작성하기가 훨씬 어렵습니다. 예외 안전.

셋째, 변수 대신 함수를 작성하는 것이 가치가 있는지 고려해 보겠습니다. 이 경우에는 ctor로 맵을 초기화하므로, operator()이 호출 될 때마다 초기화되었는지 확인하지 않아도됩니다. 또한 두 가지를 결합 할 수도 있습니다. ctor가 존재하지 않으면 그것을 초기화하고 operator()는 룩업을 수행합니다.

마지막으로, map::operator[]은 주로 항목 삽입에 유용합니다. 존재하지 않으면 지정된 키가있는 항목이 생성되지만 항목을 찾을 때는 일반적으로 항목을 만들고 싶습니다. 이를 위해서는 일반적으로 대신 map.find()을 사용하는 것이 좋습니다.

3

첫 번째 해결책은 많은 쓰레기를 만듭니다. 왜 당신은 값으로 클래스를 반환하지 않습니까? 꽤 가벼우 며 동적으로 할당해야합니다. 반환 된 클래스가 커질수록, 당신은 전력 공구를 원하는 경우

HistoParameter variable_to_parameter(char* var_name) 
{ 
    static std::map<const std::string, HistoParameter> hp; 
    if (hp.empty()) 
    { 
    hp.insert(std::make_pair("ph_pt", HistoParameter(100,0,22000))); 
    hp.insert(std::make_pair("ph_eta", HistoParameter(100,-3,3))); 
    //... 
    } 
    return hp[var_name]; 
} 

boost::flyweight을 시도합니다.

HistoParameter& variable_to_parameter(char* var_name) 
{ 
    // same code 
} 

을 ... 당신이 그것을 불변하려는 경우에도 const 던져 :

당신이 큰 구조를 다시 전달하지 않으려면, 당신은 할 수 있습니다.

편집 : Niel의 제안에 따라에 추가 make_pair가 추가되었습니다.

4

두 번째 솔루션은 나에게 확인을 보인다 - 당신은 말할 수 :

if (hp.empty()) { 
    // populate map 
} 

가 나는 또한 포인터보다는 그것을 값의 맵을 고려할 것 - 당신이 여기에 동적 할당을 필요로 표시되지 않습니다 :

를 다음
std::map <std::string, HistoParameter> hp; 

:

hp["ph_pt"] = HistoParameter(100,0,22000); 

주 당신이 명시 적 표준 : : 문자열 변환이 필요하지 않습니다. 더 나은 방법 :

hp.insert(std::make_pair("ph_pt", HistoParameter(100,0,22000))); 
+0

같은 생각이지만, 당신은 make_pair에서 나를 때렸다. 그것이 _T- 밖에 밖에없는 것을 잊어 버렸습니다. –

+0

나는 전역 변수를 사용할 수 없기 때문에 ht.empty()를 좋아한다. 나는이 클래스가 미래에 매우 다르고 무거워 질 수 있기 때문에 포인터를 사용하고 있습니다. –

+0

캡슐화를 사용하는 주된 이유 중 하나는 필요할 때 언제든지 변경할 수 있습니다. 스마트 포인터를 사용하지 않으면 리소스 누출 문제가 발생합니다. 지도가 고정되어 있기 때문에 중요하지 않지만 여전히 ... –

0

나는

InitializeHistoParameter() 
{ 
    myMap["ph_pt"] = new ... 
    myMap["ph_eta"] = new ... 
} 

그리고

HistoParameter* variable_to_parameter(char* var_name) 
{ 
    return myMap[var_name]; 
} 
0

어느쪽으로 든 메모리 누수가 발생합니다. = 연산자 예를 들어, 호출 할 때마다 :

hp[std::string("ph_pt")] = new HistoParameter(100,0,22000); 

당신이 이전 매달려 떠나, 새로운 HistoParameter 객체를 생성하고이 가장 최근의 물체로 키 "산도"페어링된다. 새로운 객체를 생성하는 때마다 실제 의도 인 경우 , 당신은 아마 new 작업 전에

delete hp[std::string("ph_pt")]; 

를 호출해야합니다.

제 생각에는 원시 new 작업을 가능한 많이 피하고 객체 수명 관리를 위해 boost::share_ptr과 같은 스마트 포인터를 사용하는 것이 좋습니다.