2012-01-28 8 views
1

나는 함수를 필요로하는 함수의 인수로 사용할 임시 함수를 만드는 시간을 절약 할 생각을 가지고있었습니다. 이 동작을 수행하는 이유는 모든 종류의 함수를 정의하지 않고도 (Win32 API를 사용하여) 새로운 스레드에서 쉬운 방식으로 작업하는 것입니다.함수 호출 내에서 함수 정의하기

void msg (const string & message) { 
    MessageBox (0, message.c_str(), "Message", 0); 
} 

이 메시지 상자를 생성합니다, 그러나 닫을 때까지 프로그램이 정지 :

다음은 예입니다. 해결 방법은 주 스레드와 동시에 실행되는 메시지 상자 용 스레드를 만드는 것입니다. 나는 그 같은 목적을 위해 다른 스레드를 원하는 여러 기능을 가지고 있기 때문에이 경우

void msg (const string & message) { 
    CreateThread (0, 0, 
    (LPTHREAD_START_ROUTINE)({MessageBox (0, message.c_str(), "Message", 0);}), 
    0, 0, 0); 
} 

LPTHREAD_START_ROUTINECreateThread에 호출 기능을 넣어,
typedef DWORD (*LPTHREAD_START_ROUTINE)(LPVOID param);

로 정의하는 것은 잘 작동하는 것 같군.

하지만 사용하고 싶다고 말하면 LPVOID param입니다. 이 방법이 얼마나 표준인지, 그리고 더 고급 기술을 위해이 방법을 사용하는 방법을 알고 싶습니다. 또한 나중에 사용할 수 있도록 함수를 임시로 저장하고 사용하지 않기 때문에 나중에 사용할 수 있도록 저장하는 기능을 알고 있습니다 (예 : 처리 할 메시지를 추가 할 수있는 메시지 루프 함수 및 호출 할 해당 함수). 필요할 때 호출 할 수 있습니다. 쓰레드와 같은 것들을 넘어선 용도가 있습니까? 한 줄을 다른 곳에서 사용하기 위해 짜증나게 만드는 곳이 있습니까?

+0

문제는 정말 명확하지 않다) stackoverflow.com :)에

덕분에이 또 다른 게시물을 찾을 수 있습니다 생각 (그리고 또한 그 구문이 아닌 표준) –

+0

난 그냥 오늘 생각을했다 : 파일에 시간과 공간을 절약하는 체계. 나는 그 사용법이 얼마나 안전한 지, 그리고 그 예보다 더 나은 것들에 사용될 수 있는지 궁금합니다. – chris

답변

2

"람다"라고합니다. 이것들은 이것 이외의 많은 목적에 매우 유용하며 C++ 11 표준에 있습니다. 최신 GCC와 MSVC에서 찾을 수 있습니다. 그러나 MSVC의 현재 구현은 표준에서 이러한 변환을 지정하지 않았으므로 함수 포인터로의 변환을 허용하지 않습니다. VC11이이 변환을 구현합니다. 이 코드는 C++ 11 표준 합치입니다 :

void msg (const string & message) { 
    CreateThread (0, 0, 
    [](LPVOID* param) { MessageBox (0, message.c_str(), "Message", 0); }, 
    0, 0, 0); 
} 
+0

'LPVOID' (='void **')가 아니고'LPVOID' (='void *') (바보 같은 윈도우'typedef's) –

+0

고마워요. 그것은 검색 할 때 관련없는 주제의 고통스러운 페이지를 쉽게 만들어줍니다. 한 가지 : LPVOID는'void *'로 정의되어 있으므로 거기에 여분의 *가 있습니다. 세스가 저에게 저를 이길 것 같아요 ... – chris

0

람다 표준되지 않은 시간에 다른 방법이 있었다 - 당신이 기능 로컬 클래스를 정의하고 해당 클래스 내에서 내부 함수를 정의 할 수는. 다음과 같이 입력하십시오 :

이제 귀하의 질문을 고려해보십시오. STL의 std :: string에 메시지 텍스트를 전달하려고했습니다. 첫 번째 스레드에 의해 해제 될 수있는 동적 메모리를 차지하므로 병렬로 실행되는 새 스레드는 메시지 텍스트를 계속 사용할 수 있어야합니다. 이 작업은 복사 (람다의 값에 의한 캡처 - [=] 소개 기능) 또는 참조 공유 (참조 계산을 통해 알려짐)를 통해 수행 할 수 있습니다. 복사를 고려해 봅시다.

void msg(const string &message) 
{ 
    struct message_box 
    { 
     static DWORD WINAPI display(void *param) 
     { 
      MessageBox(0, ((string *)param)->c_str(), "Message", 0); 
      delete (string *)param; 
      return 0; 
     } 
    }; 

    string *clone = new string(message); 

    ::CreateThread(0, 0, 
     &message_box::display, 
     clone, 0, 0); 
} 

사본은 초기 스레드에 할당되고 새 스레드에서 삭제됩니다. 이를 위해서는 CRT에서 멀티 스레딩을 지원해야합니다.

새 스레드를 시작하지 못하면 고아가 될 메모리로 끝납니다. 이 문제를 해결하자 : 메모리가 CRT에 의해 관리되고

void msg(const string &message) 
{ 
    struct message_box 
    { 
     static DWORD WINAPI display(void *param) 
     { 
      auto_ptr<string> message((string *)param); 
      MessageBox(0, message->c_str(), "Message", 0); 
      return 0; 
     } 
    }; 

    auto_ptr<string> clone(new string(message)); 

    if (::CreateThread(0, 0, &message_box::display, clone.get(), 0, 0)) 
     clone.release(); // release only if the new thread starts successfully. 
} 

때문에, CRT는 CreateThread API에 의해 수행되지 않습니다 새로운 스레드에서 초기화되어야한다.

void msg(const string &message) 
{ 
    struct message_box 
    { 
     static unsigned int WINAPI display(void *param) 
     { 
      auto_ptr<string> message((string *)param); 
      MessageBox(0, message->c_str(), "Message", 0); 
      return 0; 
     } 
    }; 

    auto_ptr<string> clone(new string(message)); 

    if (_beginthreadex(0, 0, &message_box::display, clone.get(), 0, 0)) 
     clone.release(); // release only if the new thread starts successfully. 
} 

이 솔루션은 따로 자체가 자원으로 유출되는 스레드의 문제를 잎 : 당신은 CRT beginthread/beginthreadex 대신 사용해야합니다. 그러나, 당신이

+1

CreateThread와 C 런타임의 문제는 오래전에 역사에 위임되었습니다. –

관련 문제