2017-09-12 4 views
1

저는 C++을 배우고 있으며 클래스에서 객체를 사용하려고합니다. 내 프로그램의 결과로 인해 데이터 소멸자가 두 번 호출 될 것이라고 예상했기 때문에 혼란 스럽습니다. 내 개체는 "데이터 데이터 (3);" 그리고 소멸자는 코드 블록의 끝에서 호출되어야하며 rect 소멸자가 호출 될 때 rect 내부의 데이터 소멸자도 호출되어야합니다. 예상대로 코드 블록이 끝난 후 두 번 "데이터 소멸자"를 인쇄합니다. 그러나 데이터 객체를 만든 후에도 인쇄됩니다. 왜 이런 일이 일어나고 데이터 내부의 할당 된 메모리를 올바르게 삭제할 수 있습니까?소멸자는 어디에서 호출 되었습니까?

class Data { 
private: 
    int* data; 
    int size; 
public: 
    Data() { 
     size = 10; 
     data = new int[size]; 
    } 
    Data(int size) 
     : size(size) { 
     data = new int[size]; 
    } 
    virtual ~Data() { 
     // delete data; 
     std::cout << "data destruktor" << std::endl; 
    } 
    void init(int val) { 
     for (int i = 0; i < size; i++) 
      data[i] = val; 
    } 
    int& operator[](int index) { 
     return data[index]; 
    } 
    int getSize() const { 
     return size; 
    } 
}; 

class Rect { 
private: 
    Data data; 
    int width, height; 
public: 
    Rect() {} 
    Rect(int width, int height, Data data, int val = 0) 
     : width(width), height(height), data(data) { 
     data.init(val); 
    } 
    int getWidth() const { 
     return width; 
    } 
    int getHeight() const { 
     return height; 
    } 
    int getArea() const { 
     return width * height; 
    } 
    Data& getData() { 
     return data; 
    } 
}; 

int main() { 

    { 
     Data data(3); 
     std::cout << "data created" << std::endl; 
     Rect rect(5, 4, data, 9); 
     std::cout << "end of code block" << std::endl; 
    } 

    std::cout << "end of program" << std::endl; 

    system("pause"); 
    return 0; 
} 

출력 :

당신이 사각형 생성자 호출 후에 파괴 된 데이터의 사본의 c'tor을 전달하고 따라서 귀하의 desctructor 호출입니다되기 때문이다
data created 
data destruktor 
end of code block 
data destruktor 
data destruktor 
end of program 
+0

Re "하지만 데이터 객체를 만든 후에도 출력합니다.", 값으로 'Data'를 전달 중입니다. 임시 객체가 생성됩니다. 어느 것이 파괴되는지. 모든 것이 정상적으로 작동하며'init' 멤버 함수를 정의하는 데 도움이되는 조언을 제외하고는 아무 것도 걱정할 필요가 없습니다. 그냥 그렇게하지 말고 그 충고의 출처를 "아주 용의성이 있고, 그 사람의 진술이 의심 스럽다"범주에 두십시오. 오, 미안, 나는 보지 못했다. ** 당신은 복사 생성자가 없다. **. 이렇게하면 배열을 두 번 삭제할 수 있습니다. 정의되지 않은 동작입니다. 대신'std :: vector'를 사용하십시오! –

+0

@ Cheersandhth.-Alf 함수 매개 변수는 임시 개체가 아닙니다 –

+1

Rect 개체를 구성하면 값에 따라 'data'변수가 전달됩니다. 이렇게하면 해당 객체의 사본이 만들어지며 Rect 객체의 반환 후에 destructed됩니다. 그게 혼란을 일으키는 원인이라고 생각합니다. –

답변

0

. 현재 값으로 Data을 전달하는

0
Rect(int width, int height, Data data, int val = 0) 

은, 그래서 새가 작성하고이 메서드를 호출 할 때 파괴됩니다. 그것은해야한다 : 어쩌면 const Data &data

Rect(int width, int height, Data &data, int val = 0) 

나 : Rect 이미 자신의 일이있을 때 당신이 Data을 전달하는 이유는 명확하지 않다.

Rect(int width, int height, const Data &data, int val = 0) 
: data(data) 
// ... 

NB 당신은 delete data; 라인을해야합니까 @ P0W 지적 실제로 delete[] data;로 : 어쩌면 당신은-복사 할당을하거나 복사 구성을 할 수 shoudl. Data::Data(const Data&)의 복사 생성자도 마찬가지입니다.

+1

다른 문제는 두 번 삭제되고 잠재적으로 충돌/UB가 발생하는 복사 생성자가 누락되었습니다. 또한 delete는'delete [] data;이어야한다. – P0W

관련 문제