2011-12-20 3 views
8

나는 이것이 더 이상 필요하지 않을 때 내 코드의 어느 부분이 동적으로 할당되었지만 정적 인 클래스 멤버를 해제할지 궁금했다. 다음 코드를 참조하십시오. classPrinter은 모든 A- 개체간에 공유되며 A 클래스의 첫 번째 인스턴스를 만들 때 만들어집니다. 확실한 것은 : classPrinter- 개체가 내 프로그램을 종료 할 때 자동으로 파괴됩니다. 맞습니까?C++ 정적 클래스 멤버는 엉망진창을 청소합니까?

a.h

class A { 
static B* classPrinter; 
} 

a.cpp

#include "a.h" 
B A::classPrinter = new B(); 

A::A() { ...} 
+3

적어도 동적 할당이 필요한 경우 스마트 포인터가 좋습니다 ([sbi 's answer] (http://stackoverflow.com/a/8578256/10077 참조). –

+1

Ack .... static pointer == evy. –

답변

19

내 프로그램을 종료 할 때 somePrinter- 개체가 자동으로 삭제됩니다. 맞습니까?

이 코드는 C++이므로 대답은 "아니오"입니다. new으로 할당 된 모든 것에 대해 해당 delete을 호출해야합니다. 그렇게하지 않으면 개체가 누출됩니다. 그러나 동적으로 할당하는 이유는 무엇입니까? 그 classPrinter이 프로그램의 마지막에 파괴 될 것이다 제외하고이

class A { 
    static B classPrinter; 
} 

B A::classPrinter; 

, 당신의 코드처럼 동작합니다.

그러나, 당신은 클래스 A의 첫 번째 인스턴스를 생성 할 때

classPrinter 모든 A-객체간에 공유되어 생성되는 물품.

질문의 코드는이 작업을 수행하지 않습니다. 스마트 포인터가 개체가 삭제됩니다 있는지 확인합니다

class A { 
    static std::shared_ptr<B> classPrinter; 
} 

std::shared_ptr<B> A::classPrinter; 

A::A() 
{ 
    if(!classPrinter) 
    classPrinter.reset(new B()); 
} 

:이 작업을 수행 할 경우 ,이 같은 뭔가.

+1

"은 모든 A- 객체를 만들고 클래스 A의 첫 번째 인스턴스가 만들어 질 때 만들어집니다. " – pezcode

+0

@pezcode : 클래스 A의 첫 번째 인스턴스가 만들어 질 때 생성 된 것을 참조한다고 생각합니다.하지만 그 질문의 코드는 동일합니다 내 코드로 (물론 누출 제외). – sbi

+0

새 연산자가 오버로드 될 수 있습니다, 나는 그 사건이 아니라 생각하지만, 가능한 이론적으로. – Yola

3

A::classPrinter 포인트가 호출되지 않습니다 할 수있는 개체의 소멸자.

당신이 생각하는 경우에 그것은 논리 외에는 아무것도 아닙니다; 일치하는 부분은 어디에 있습니까? delete - 일반적인 경우 객체의 dtor를 호출합니다.

점령 된 메모리는 다시 비공개로 표시되어 시스템에 반환됩니다.

+0

@sbi 의견 앞뒤에 내 게시물을 편집 할 기회가 있었는지 확실하지 않지만 이해하기 쉽도록 문구를 변경했습니다. –

0

A::classPrinter을 여러 구성원이 공유하는 경우 원시 포인터 대신 std :: shared_ptr을 사용할 수 있습니까? 그것에 대한 모든 참조가 사라지면 자동으로 삭제됩니다.

그러나 예, 메모리가 적어도 내가 생각할 수있는 모든 OS 년대에, 프로그램이 종료 한 후 재생됩니다 ...

0

당신은 어떤 래퍼를 만들거나 dtor 전화를 보장 할 수있는 shared_ptr 같은 것을 사용해야합니다.

10

아니요, new을 사용하여 만든 개체는 절대로 자동 삭제되지 않습니다.메모리 누출을 막기 위해 항상 일치하는 delete을 제공해야합니다.

이 경우 가장 간단한 해결책은 동적 개체에 대한 정적 포인터가 아닌 정적 개체를 사용하는 것입니다. 추가 수준의 간접 참조가 필요하지 않습니다.

// header file 
class A { 
    static B classPrinter; 
}; 

// source file 
B A::classPrinter; 

또는 개체가 필요할 때까지 건설을 지연 (다른 번역 단위로 정적 객체가 생성자에서 액세스해야하는 경우 잠재적 인 문제를 피할 수)하려면 :

class A { 
    static B & classPrinter() { 
     static B instance; 
     return instance; 
    } 
}; 

을 기타에서 동적 할당이 실제로 필요할 때는 스마트 포인터 또는 기타 RAII 개체를 사용하여 항상 동적 개체를 관리해야합니다.

+1

로컬 static은 멋진 트릭이다. '+ 1'은 나에게서. – sbi

0

정적 (정적 멤버 변수까지)은 본질적으로 항상 존재 함을 의미합니다.

정적 포인터를 만들면 의미가있는 지점에서 할당을 해제 할 수 없습니다. 더 많은 문맥이 필요합니다.

정적 멤버 소유자 클래스의 인스턴스가있는 동안에 만 존재하는 공유 데이터가 필요하면 정적 카운터가 필요합니다. 인스턴스 및 카운터 == 0.를 만들 때마다 새 정적 값을 할당하십시오. 소유자 클래스의 마지막 인스턴스를 삭제할 때마다 현재 정적 값의 할당을 해제합니다.

그렇지 않으면 공유 또는 스마트 포인터 같은 것을 할당 해제해야하지만 문제가 발생할 수도 있습니다. 스마트 포인터가 더 이상 참조 및 할당 해제를 볼 수 없으면 너무 일찍 처리 할 수 ​​있습니다. 할당이 해제 된 상태라면 정보를 다시 필요로 할 때 그 의미는 무엇입니까? 새로운 정적 값을 할당합니까?

소유자 클래스의 인스턴스가 있는지 여부에 관계없이 정적 멤버가 항상 존재해야하는 경우 포인터를 참조 또는 인스턴스로 변경하는 것이 좋습니다.

관련 문제