2012-10-21 6 views
2

코드 해제 구성 : 생성자 throw 1; 다음
C++ 비 완전히 객체

#include<iostream> 
using namespace std; 
class A{ 
    public: 
    A(){cout << "A() Constructor " << endl; 
     throw 1; 
    } 

}; 


int main(){ 
A* p=0; 
cout << p << endl; // p value is 0 
try{ 
p=new A(); // object is not fully constructed, no address is returned to p. for future deallocation 

} 
catch(...){cout << "Exception" << endl;} 
cout << p << endl; // this will output that p has the value 0,proof that no address was returned to p. 


} 

메모리가 힙에있는 객체에 할당 된 메모리의 주소가 생성자 에 전달 되나의 목적을 유형 A은 완전히 구성된 오브젝트로 간주되지 않습니다. 따라서 포인터는 포인터 p로 리턴됩니다. 내가 뭔가 잘못 이해했다면 나를 바로 잡아라.

질문 :
1) 그래서 내 질문이이 (가) 개체에 대한 메모리 할당을 해제하는 등의 경우에 가능한 방법이다. 임에 대해 말하지 않고 소멸자 호출이지만 메모리 할당 해제.

2)Amain 함수 안에 로컬 객체를 만들면 어떨까요? 그리고 분명히 그것은 완전히 건설되지 않을 것입니다. 이 객체는 언제 할당이 해제됩니다 (완전히 구속 된 하위 객체의 소멸자를 호출 한 후).

+0

p가 null 포인터이고 A 객체가 할당 된 메모리 주소가 A 생성자 내에서 throw 된 예외 때문에이 포인터에 전달되지 않았기 때문에 삭제할 수 없습니다. – AlexDan

+1

올바른 방법 이를 공유 포인터라고합니다. – Florian

답변

4

할당은 다수의 단계로 구성

  1. operator new(sizeof(A))를 사용하여 메모리를 할당한다.
  2. 할당 된 메모리에서 개체를 기본 구성하려고합니다.
  3. 기본 구성이 실패하면 앞에서 얻은 주소로 operator delete(x)이 호출됩니다. 당신이 사용하는 경우

은 더 일반적으로, 오버로드 operator new(), 예를 들어, operator new(size_t, Alloctor)를 호출 new(allocator) A() (allocatorAllocator으로 변환 임), 해당 operator delete()가 호출됩니다.

예외를 throw하는 과정에서 부분적으로 구성된 모든 하위 객체가 파괴됩니다 (생성 된 역순). 즉, 객체 생성자에서 예외가 발생하면 정리 (모든 하위 객체가 할당 된 자원을 올바르게 관리한다고 가정)를 신경 쓸 필요가 없습니다. 이는 힙이나 스택에 개체가 할당되었는지 여부에 관계없이 true입니다.

+0

클래스에 "A * p"가 있으면 p = new A();로이 포인터를 초기화합니다. 나는이 메모리를 ~ A() 소멸자로부터 할당 해제하려고했다. 그래서 A() 생성자가 소멸자가 호출되는 것을 방지하는 예외를 throw하기 때문에 p가 가리키는 메모리를 할당 해제 할 수 없습니다. 이 상황에서 나는 무엇을해야합니까? – AlexDan

5

1) 할당 해제가 완료되었습니다.

2) 로컬 개체 인 경우 할당되지 않은 개체입니다.

+0

로컬 객체의 경우, 왜 처음에는 할당되지 않을까요? 내가 무엇을 알고있는 로컬 객체는 실행 흐름이 존재하는 범위에 들어갈 때 할당되고, 그 후 생성자는 그 메모리에서 호출된다. 실행이 범위에 들어 왔을 때 이미 할당되었습니다. 그래서 어떻게 그들이 처음에 배당되지 않을 가능성이 있습니까? – AlexDan

+0

나는 개체의 존재에 대해 당신과 동의 할 수 있습니다. 객체가 생성자가 실패하면 절대 존재하지 않지만 메모리에 할당되지 않았다는 것을 의미하지는 않습니다. 이는 로컬 객체와 동적 객체 모두 동일합니다. 내가 틀린 것을 이해하면 나를 바로 잡아라. – AlexDan

+0

나를 위해 할당은 새로운 또는 malloc으로 힙 할당을 의미합니다. 분명히 지역 객체는 메모리의 어딘가에 놓여 야하지만, 어떻게 이런 일이 일어나는지는 여러분이 통제 할 수있는 것이 아니기 때문에 걱정할 필요가 없습니다. 그냥 발생하고 그냥 작동합니다. – john

5

생성자가 해당 객체에 할당 된 메모리를 자동으로 throw하면 소멸자가 호출되지 않습니다. 할당을 해제 할 필요는 없습니다. new A() 수행

+0

예 객체가 완전히 구성되지 않았기 때문에 소멸자가 호출되지 않는다는 것을 알고 있습니다. 대답에서. 두 경우 모두, 생성자가 예외를 던진 후 로컬 객체와 동적 할당 메모리가 자동으로 할당 된 메모리가 해제된다는 것을 이해할 수 있습니까? – AlexDan

+0

예. 관계없이 개체가 생성되는 방법에 관계없이 생성자가 메모리를 자동으로 할당 해제합니다. –

1

CPP에서 생성자 (ctor에), 호출 시퀀스는 다음

  • 가상 기본 클래스 : 가상베이스의 ctor는, 깊이 제 1 시퀀스에 따른 호출.
  • 기본 클래스 : 클래스를 정의 할 때 파생 선언에 따라 기본 클래스를 호출하는 시퀀스입니다.
  • 비 정적 멤버 개체
  • 파생 클래스 ctor;

소멸자 (dtor)는 역순으로 호출됩니다.

CPP는 완전히 생성 된 개체 (포인터가 아님)의 리소스가 해제 될 것임을 보장합니다.

RAII (Resource Acquisition Is Initialization)가 있습니다. 우리는 객체를 사용하여 메모리를 할당하는 원시 포인터를 래핑 한 다음 dtor에서 메모리를 해제합니다. 파생 된 객체가 (메모리가 충분하지 않거나 예외 등으로 인해) 부분적으로 생성 된 경우 멤버 객체 dtor가 호출됩니다.

위의 간단한 예제에서는 할당 된 리소스가 없으므로 리소스가 누출되지 않습니다.

그러나 throw 전에 메모리를 할당하는 멤버 포인터가 있으면 메모리 누수가 발생합니다. 클래스에서 메모리를 래핑하고이 클래스의 객체를 구성 요소로 사용하면 (RAII 사용) 메모리 누수가 발생하지 않습니다.

관련 문제