2010-12-09 7 views
1

나는 이것을 수행하는 방법에 대해 약간 혼란 스럽다. 예를 들어 메모리를 할당하는 클래스가 있다고 가정 해보십시오. 나는 자동차처럼 자기 파괴를 원하지만, 알 수없는 어떤 이유 때문에 그것을 벡터에 넣는다. 내 소멸자가 카운터 1에서 두 번 모두 호출되는이 경우 C++ 기초, 벡터, 소멸자

#include <iostream> 
#include <vector> 
class Test { 
public: 
    Test(); 
    Test(int a); 
    virtual ~Test(); 
    int counter; 
    Test * otherTest; 
}; 

volatile int count = 0; 


Test::Test(int a) { 
    count++; 
    counter = count; 
    std::cout << counter << "Got constructed!\n"; 
    otherTest = new Test(); 
    otherTest->counter = 999; 
} 

Test::Test() { 
    count++; 
    counter = count; 
    std::cout << counter << "Alloced got constructed!\n"; 
    otherTest = NULL; 
} 


Test::~Test() { 
    if(otherTest != 0){ 
    std::cout << otherTest->counter << " 1Got destructed" << counter << "\n"; 
    otherTest->counter = 888; 
    std::cout << otherTest->counter << " 2Got destructed" << counter << "\n"; 
    } 
} 

int vectorTest(){ 
    Test a(5); 
    std::vector<Test> vecTest; 
    vecTest.push_back(a); 
    return 1; 
} 

int main(){ 
    std::cout << "HELLO WORLD\n"; 
    vectorTest(); 
    std::cout << "Prog finished\n"; 
} 

는 ALLOC '개체가 이미 888로 설정 (또는 삭제 된 개체에 잘못된 접근으로 이어지는 해방 된 진정한 경우)하고있다. 지역 변수를 벡터에 넣는 올바른 경우는 현명하게 발생하지 않는 일종의 디자인입니다. 다음은 다르게 동작하며 소멸자는 한 번만 호출됩니다.

int vectorTest(){ 
    //Test a(5); 
    std::vector<Test> vecTest; 
    vecTest.push_back(*(new Test(5))); 
    return 1; 
} 

어떻게 로컬 변수가 소멸자를 한 번만 호출하면 동일한 동작을하도록 할 수 있습니까? 지역을 단순히 벡터에 넣지 않겠습니까? 그러나 벡터가 배열보다 선호되지 않는다면, 로컬 객체의로드가 있다면 별도로 초기화하고 벡터에 배치하여 프리/힙 메모리를 사용하지 않고 다른 함수에 전달할 수 있습니까? 나는 여기서 중요한 무엇인가 놓치고 있다고 생각한다. 이것은 소유권을 이전하는 일종의 스마트 포인터의 경우입니까?

+0

@ 감사합니다. 편집 해 주셔서 감사합니다. – karlphillip

+1

나중에 코드를 선택하고 코드 아이콘 '101010'을 클릭하여 자신의 코드를 포맷 할 수 있습니다. –

답변

9

벡터는 자체 저장 공간을 유지하고 그 안에 값을 복사합니다. 복사 생성자를 구현하지 않았으므로 기본 값이 사용되며 이는 포인터의 값을 복사합니다. 따라서이 포인터는 지역 변수 소멸자에 의해 한 번, 벡터에 의해 한 번 두 번 삭제됩니다. rule of three을 잊지 마세요. 복사 및 할당 연산자를 구현하거나 shared_ptr과 같이 이미이 작업을 수행하는 클래스 만 사용해야합니다. 새로 할당 된 객체 때문에이 라인은, 메모리 누수가 발생한다는

참고는 삭제되지 않습니다 :

다크 팔콘 쓴 외에도
vecTest.push_back(*(new Test(5))); 
1

: 일반적으로 벡터에 삽입 할 때 재 할당을 방지하기 위해 벡터에서 기본 구성 요소로 로컬 요소를 교체하는 스왑 함수를 구현합니다. 스왑은 포인터의 소유권을 교환 할 것이고 모든 것이 잘 될 것입니다. 새로운 C++ 0x는이 문제를 해결하기 위해 rvalue-references를 통해 이동 의미를가집니다.

1

아마도 Test 객체 대신 Test 객체에 대한 포인터를 벡터에 보관하는 것이 좋습니다. 이는 힙에 메모리를 할당하는 객체 (이 테스트 객체와 같은)에 특히 해당됩니다. 벡터에서 임의의 알고리즘 (예 : std :: sort)을 사용하면 결국 알고리즘은 메모리를 할당하고 할당을 취소합니다 (실질적으로 속도가 느려집니다).