2016-08-22 2 views
4

std::functionstd::map을 사용하여 콜백 시스템을 만들고 있습니다. 지도는 int을 키로 사용하며 값은 std::function입니다. 나는 그 함수에 메소드를 묶는다. map.erase(i)을 호출하면 메모리에서 std :: function을 삭제할 것인가, 아니면 메모리 누수가 발생합니까?std :: function 람다 랩핑 된 메소드를 std :: map에서 제거하기

#include <iostream> 
#include <functional> 
#include <map> 

using namespace std; 

class TestClass{ 
    public: 
     TestClass(int _i, map<int, function<void()>>& test_map):i(_i){ 
      test_map[i]=[&](){this->lambda_test();}; 
     }; 
     void lambda_test(){cout << "output" << " " << i<< endl;}; 
    private: 
     int i; 
}; 

int main() { 
    map<int, function<void()>> test_map; 
    TestClass* test = new TestClass(1, test_map); 
    test_map[1](); 
    delete test; 
    test_map.erase(1); // <-- here 
    };     

마지막 test_map.erase(1); 메모리에서 std::function를 제거합니까 : 여기

몇 가지 예제 코드인가? 여기에 실제 메모리 할당의 측면에서 람다와 어떤 일이 일어나는지의 아주 좋은 설명이 있습니다

+0

이 코드에서주의해야 할 것은'delete test;와'test_map.erase (1);'사이에 있으며, 여기서 람다는 매달려있는'this' 포인터를 참조하고 있습니다. 이 예에서는 유해하지 않지만 '증가하는'응용 프로그램이나 멀티 스레드 응용 프로그램은 정의되지 않은 동작을 시작할 수 있습니다. 일반적으로 람다 대신 맵에 TestClass를 저장하여 해결할 수있는 이상한 평생 문제가 있습니다. – stefaanv

답변

3

이것은 좋은 코드는 아니지만 메모리 누수가 없습니다. 당신은 std::functionstd::map에 (포인터가 아닌) 값으로 저장하고 있으므로 std::map::erase은 소멸자를 std::function이라고 부를 것입니다.

다른 말로하면 이 아니기 때문에 std::function을 보내지 않으므로 delete이면 std::function이 필요하지 않습니다.

+0

무엇이 좋지 않은 코드입니까? 지도에 실제 객체가 아닌 std :: function 포인터를 저장해야합니까? –

+0

호기심에서이 코드에 관해 특히 '좋지 않은'점은 무엇입니까? – sji

+0

@MaxTyler 왜 새로운 'TestClass'인가? 'TestClass'는 여기서 무엇을하고 있습니까? 이 예제가 장난감이라는 것을 이해합니다.하지만 실제 코드에서이 패턴과 비슷한 것을 사용한다면 설계상의 결함을 의심 할 수 있습니다. – Daniel

1

:

https://stackoverflow.com/a/12203426/1230538

내가 알고있는 것처럼, 람다 구문은 r 값, 복사를 (생성 캡처 한 상태 등)를 std :: function에 저장합니다. 이것은 std :: function의 소멸자에 의해 지워지 며, 지우개를 호출 할 때 std :: map의 소멸자가 호출합니다 (그리고/또는지도가 범위를 벗어날 때).