2016-07-27 3 views
-1

unordered_map 타입이 <const char *, std::list<void *>>이고 일부 조건에서 일치하는지 확인하기 위해 반복되는 값 목록이 있습니다. 일치하는 것이 있으면 값의 인덱스에있는 std :: list에 특정 값에 대한 포인터를 추가하려고합니다.std :: unordered_map의 std :: list 요소를 초기화하는 중

const char *handler_name = NULL; 
while (handler_name = all_handlers->get(), handler_name) 
{ 
    if (condition) 
    { 
     //Add pointer element to every event handler it registers 
     std::list<void *> scripts = responders[handler_name]; 
     if (scripts.size() == 0) 
     { 
      responders[handler_name] = scripts; 
     } 
     scripts.push_back(static_cast<void *> (L)); 
     active_states[static_cast<void *> (L)] = 1; //set to active so we only delete it once 
    } 
    handler_name = NULL; 
} 

이 내 변수 선언은 다음과 같습니다

private: 
    std::unordered_map<const char*, std::list<void *>> responders; 
    std::unordered_map<void *, int> active_states; 

all_handlers 잠재적 키로 사용할 CONST의 char *의 C 문자열을 모두 얻을 unconventionally 만약 내가 올바르게 이상 반복하고 사용자 지정 목록 유형입니다 , 조건에 일치가있는 경우.

그러나 gdb는 std :: list가 관심 키에 대해 초기화되지 않는다는 것을 보여 주며, handler_name의 모든 값에 대해 std :: list를 초기화하는 것에 대한 두려움과 관련이 있다고 생각합니다. 새로운 값을 추가하기 전에 항목이 이미 존재하는지 확인해야합니다.

이 경우 적절한 초기화를 수행하는 가장 좋은 방법은 무엇입니까?

+3

[MCVE] –

+0

@ m.s.:'조건'과 별개로,이 질문은 내게 완전히 완성 된 것처럼 보입니다. OP는 명확하게 '초기화'를 이해하는 데 문제가 있으며 참조와 값의 차이를 알지 못합니다. – xtofl

+1

아직 완성되지 않았습니다. 'all_handlers' 란 무엇입니까? 'const char * '값은 어디서 오는 것입니까? OP는 같은 내용을 가진 문자열 리터럴이'=='을 사용하여 equal이라는 것을 가정하고 있습니까? 여기에는 몇 가지 가정이 있습니다. –

답변

0
const char* handler_name = NULL; 
while (handler_name = all_handlers->get(), handler_name) 

이 루프를 작성하는 관용적 방법이 아니다!. 사실 그것은 입니다. 매우입니다.

const char* handler_name = NULL; 
while ((handler_name = all_handlers->get())) 

(이중 괄호 === 사이의 혼동에 대한 경고를 발행하는 일부 컴파일러를 방지하기 위해 필요) :

은보다 전통적인 접근 방법을 고려한다.

또는 대신 for를 사용하여이 :

for (const char* handler_name = all_handlers->get(); handler_name; handler_name = all_handlers->get()) 

handler_name의 모든 값에 대한 표준 : : 목록을 초기화 대한 두려움,

나는 이것이 무엇을 의미하는지 모른다. responders[handler_name] 표현식은 이미 맵에 값이 없으면 그 값에 대해 std::list 공란을 초기화합니다. 그러나 그것이 당신이해야 할 일입니다. std::list을 반환은 responders[handler_name]을 평가

std::list<void *> scripts = responders[handler_name]; 
    if (scripts.size() == 0) 
    { 
     responders[handler_name] = scripts; 
    } 
    scripts.push_back(static_cast<void *> (L)); 

먼저, (이미 거기 경우 빈 하나를 만드는) 그 키에 대응 :

이것은 넌센스이다.

그런 다음이 목록을 scripts이라는 새 개체에 복사합니다. scripts 다음 비어 있지 않은, 그래서 만약 scripts는, 맵의 값의 사본 아이오와 때문에

그런 scripts 경우, 완전히 무의미합니다 scripts을 (복사하여 맵의 값을 대체하여 비어 있지 지도에있는 하나는 이미 비어 있지 않습니다.) 당신은지도에 저장된 목록에 어떤 항목을 추가하지 않도록

그런 다음 마지막으로 당신은 루프의 끝에서 범위를 벗어나 로컬 변수 목록, scripts사본을 수정합니다.

동시에 항목을 검사하여 목록이 이미 존재하는지 확인한 다음 새 값을 추가해야합니다.

그렇게하지 않아도됩니다. responses[handler_name] 그게 당신을 위해. 해당 키에 대한 항목이 없으면 항목이 만들어집니다.

이 경우 적절한 초기화를 수행하는 가장 좋은 방법은 무엇입니까?

아무 것도 걱정하지 말고 무의미한 코드를 작성하여 문제가 발생하지 않도록하십시오. responses[handler_name]은 필요한 모든 초기화를 수행합니다. 해당 키에 해당하는 목록을 찾고 목록이 없으면 빈 목록이 제대로 초기화됩니다. 넌센스의 전체 덩어리가 간단하게 기록 할 수

: 어떤 포인터가 암시 적으로 void*로 변환하기 때문에

responses[handler_name].push_back(static_cast<void *> (L)); 
    active_states[static_cast<void *> (L)] = 1; //set to active so we only delete it once 

static_cast<void*> 아마도 필요하지 않습니다. 당신이 변환에 대한 자세한 명시 할 경우를 유지할 수 있습니다,하지만 난 단순히 작성합니다

for (auto handler_name = all_handlers->get(); handler_name; handler_name = all_handlers->get()) 
{ 
    if (condition) 
    { 
     //Add Lua state to every event handler it registers 
     responses[handler_name].push_back(L); 
     active_states[L] = 1; //set to active so we only delete it once 
    } 
} 

이것은, 훨씬 짧은 훨씬 간단하고하지 않는 문제를 해결하기 뒤죽박죽 코드가 포함되어 있지 않습니다 있다.

+0

당신이 쓰는 것은 진리를 담고 있지만, 개인적으로 나는 그것의 표현에 의해 약간 모욕감을 느낄 것입니다. – xtofl

+1

@xtofl하지 않을 것입니다. 코드는 객관적으로 난센스이거나, 적어도 무의미하게 난독 화 될 수 있습니다. 그렇다면 그대로 서술해야합니다. 불쾌하거나 개인적인 것은 없습니다. 그리고 누군가가 가질 수있는 모든 가능한, 오해의 감정적 인 반응에 대해 어린 이용 장갑을 칠할 이유가 없습니다. 어쨌든, 원한다면 불만을 제기하고, 저자와 의견을 나눌 수 있습니다. –

+0

내 의견은 코드에 관한 것이지, 저자에 관한 것이 아닙니다. 컨테이너에서 객체를 복사 한 다음 다시 조건부로 복사하면 다시 무의미합니다. 이는 단순히 스타일이 좋지 않거나 약간 비효율적 일뿐 아니라 완전히 중복되어 문제를 해결하는 데 도움이되지 않습니다. 나는 "여기에 더 좋은 방법이있다"고 말한 것이 아니라, 강조하고 싶었다. 훌륭한 프로그래밍을 위해서는 명확한 사고와 올바른 이해를 바탕으로 한 신중한 행동이 필요합니다 (특히 C++). –

1

... 당신의 condition는, 상시 거짓 표현하지 가정

귀하의 list 즉시 항목이 responders지도에 추가로 초기화됩니다. C++입니다. '초기화되지 않은'목록을 가질 수 없습니다. 그들은 완전히 건설되었거나 존재하지 않습니다.

이 코드 조각 (RAII에 Readup) :

std::list<void *> scripts = responders[handler_name]; 
    if (scripts.size() == 0) 
    { 
     responders[handler_name] = scripts; 
    } 

은 no-op입니다. scripts 변수는 responders[handler_name]에서 으로 복사되었습니다. (값 의미!)입니다.

auto & scripts = responders[handler_name]; 
scripts.push_back(static_cast<void *> (L)); 

(참고 : 후자가 비어있는 경우, 당신은 단지

은 아마 당신이에 에게 항목의 목록을 참조를 가지고, 그에 추가 할 말은 ... 다시 복사하는 : 목록이 비어있는 경우 모든 당신이 알고 싶은 경우,보다 명확 list.empty()을 ... 사용 Express intent)

관련 문제