2013-07-23 3 views
1

OK .. 이렇게하면 혼란 스럽습니다. 나는 약간의 레거시 C++ 코드 부분을 다루고 있는데 그 중 일부분은 내가 안전하다고 느끼지는 않지만 100 % 확신 할 수는 없다. 다음은 스 니펫입니다 (예 : 위험한 물건).C++ 포인터 삭제시

struct A { 
    A() : a_ptr(0) {} 
    A(some_type *ptr) : a_ptr(ptr) {} 
    const some_type *a_ptr; 
}; 

struct B { 
    B() : b_ptr(0) {} 
    B(some_type *ptr) : b_ptr(ptr) {} 
    const some_type *b_ptr; 
}; 

struct Data { 
    Data(...) {//-Stuff that doesn't invole aptr_list or bptr_list; 
    } 
    ~Data() { 
     for(std::vector<A*>::iterator itr = aptr_list.begin(); itr != aptr_list.end() ++itr) { 
      delete *itr; 
     } 
     for(std::vector<B*>::iterator itr = bptr_list.begin(); itr != bptr_list.end() ++itr) { 
      delete *itr; 
     } 
    } 
    std::vector<A*> aptr_list; 
    std::vector<B*> bptr_list; 
private: 
    Data(const Data&); 
    Data& operator=(const Data&); 
}; 

그런 다음 구현, 내가 찾을 :

void some_func(...) { 
    //-Inside some function 
    Data& d = get_data(...); 
    ... 
    for(...) { 
     some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer); 
     A* a = new A(sptr); 
     B* b = new B(sptr); 
     d.aptr_list.push_back(a); 
     d.bptr_list.push_back(b); 
    } 
} 

내가 sptr 위의 구현에 사용되는 같은 포인터에 대해 조금 불안이다; 이것은 Data의 소멸자가 호출 될 때 문제가 발생합니까? 반면에 우리는 A*B*에 대해 정확히 두 개의 delete을 호출하기 때문에 Data의 소멸자가 깊지 않다면 - 그리고 어쩌면 그것이 내가 명확한 설명을 필요로하는 곳일 수 있습니다. 우려는 잘못 되었습니까? 예를 들어 구조체 AB에는 정의 된 소멸자가 없으므로 깊이가 없다는 것을 알았습니다. 그러나 이것이 포인터 데이터가 해제되는지 아닌지 확실하지 않습니다. 늘 그렇듯이 전문가의 통찰력을 인정하십시오.

시간 내 주셔서 감사합니다.

답변

2

AB 그렇게 INSIDE 아무것도 a 또는 b가 파괴됩니다, 사용자 정의 소멸자를하지 않습니다 (이 최대 해제되지 보유하고있는 실제 메모리 이외하지만 sptr은 그냥 유지되기 때문에, 그것은 deleted되는되지 않음). [A 또는 B에 다른 클래스가 포함 된 경우, 예를 들어 std::string 또는 std::vector이라고 말하면 해당 클래스는 삭제됩니다.]

그래서, 즉, 코드가이처럼 잘입니다

- absptr의 사본을 보유하고 있지만, 나중에 삭제 필요가있는 경우는, 코드의이 비트의 [삭제 적이 없어요, 그건 다른 문제입니다 ].

+0

감사합니다. 안심입니다. :-) –

1

sptr은 A 또는 B 소유가 아니므로 정확합니다.

+0

'* sptr '의 수명은 그것을 사용하는'B'와'B' 객체의 수명을 포함합니다. –

+0

사실, 질문은 Data :: ~ Data의 호출에 관한 것이 었습니다. – MSalters

+0

감사합니다 @ 마케터 :하지만 옳은 것은 무엇입니까? –

2

Data::~Data()sptr 포인터를 파괴하지 않습니다. A::~A()B::~B()으로 전화합니다.

뭘하고 싶은지 잘 모르겠지만 심 파손을 원할 경우 이미 누군가가 해방 한 메모리 주소를 비우지 않아야합니다.

구현 요구 사항에 따라 다르지만 개체를 ​​할당 한 사용자는 무료로 제공하는 것이 이상적입니다. 따라서이 sptr은 누군가 다른 사람이 할당 한 것이므로 자유롭게하면 매달린 포인터를 얻을 수 있습니다.

1

코드가 일 때 코드가 누설 될 수 있습니다.

d.aptr_list.push_back()이 더 많은 용량을 예약해야하는 경우 ab이 가리키는 메모리가 누출됩니다.

for(...) { 
    some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer); 
    A* a = new A(sptr);   // Allocate memory 
    B* b = new B(sptr)   // Allocate memory (and missing semicolon!!) 
    d.aptr_list.push_back(a); // If this fails, 
    d.bptr_list.push_back(b); // or this, 
}         // then exception is thrown and memory is lost 
            // (unless you catch the exception and 
            // perform a delete). 

당신은 안전에 대한 포인터 주위에 포장 std::unique_ptr 같은 스마트 포인터를 사용해야합니다.

귀하의 목록은 std::vector<std::unique_ptr<A>>std::vector<std::unique_ptr<B>>이어야합니다.

some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer); 
d.aptr_list.push_back(std::unique_ptr<A>(new A(sptr))); 
d.bptr_list.push_back(std::unique_ptr<B>(new B(sptr)));