2012-03-03 3 views
1

이 질문은 C++에서 메모리 할당 및 할당 취소에 관한 것입니다. 그 객체 그때 메모리를 할당하고 방법 foo는이 반환 :반환 후 C++ 메모리 할당 취소

Object foo() { 
    Object *a = new Object(); 
    // Do something with this object... 
    return *a; 
} 

이 반환 된 객체 사용하는 다른 방법 : 여기 상황이다

void bar() { 
    Object a = foo(); 
    // Do something.. 
} 

을 그리고 내 질문에,이다 어느 시점에서 내가 할당 한 메모리를 할당 해제해야합니까? 메소드 foo에서 돌아 왔을 때, 메소드 막대가 그 객체의 복사본을 스택에 갖게 되었습니까? 아니면 메모리의 한 객체에 액세스 할 수 있습니까?

감사합니다. 바트

+2

메모리를 새로 할당하면 안됩니다. – PlasmaHH

+0

@PlasmaHH - 왜 안 되니? –

+0

당신이 포인터를 반환하지 않기 때문에,하지만 개체의 복사본. – P3trus

답변

5

해당 개체의 할당을 해제 할 수 없습니다. 길을 잃었 어. 그것은 메모리 누수입니다. 처음에는 동적 할당을해서는 안됩니다. 내가 메소드 foo는에서 돌아 오면

Object foo() { 
    Object a; 
    // Do something with this object... 
    return a; 
} 

이 방법 바가 스택에 객체 의 사본을 얻을 않거나은 하나의 객체 에 액세스 할 수 있습니다 않습니다 귀하의 코드는 다음과 봤어야 어딘가에있는 기억?

여전히 액세스 할 수없는 개체의 복사본입니다.

+0

스택에 메모리를 할당하지 않습니까? – user1096294

+0

@ user1096294 : 가능합니다. –

+0

@ user1096294 : 사실 저는 언어 변호사가 저를 사냥하기 전에 제 자신을 바로 잡아야합니다. 객체는 자동 저장 기간으로 할당됩니다. 실제로는 일반적으로 스택에 할당됩니다. –

0

이 예에서는 그렇게 할 수 없습니다. 호출자 함수는 동적 객체가 어디서 만들어 졌는지 (심지어 인식)조차 알 수 없기 때문에. 참조 (또는 포인터)를 사용하려면 호출자가 사용을 끝낼 때이를 해제해야합니다.

+0

참조를 절대 삭제하면 안됩니다. 그리고 포인터를 지워야하는지 (문서를 읽지 않고) 말하면 절대로 알 수 없으므로 오류가 발생하기 쉽습니다. 결과적으로 우리는 소유권이 C++에서 문제가 될 때 포인터로 객체를 전달하지 않습니다 (이렇게하면 C가 매우 좋아집니다). 대신 우리는 동적으로 할당 된 객체의 소유권 의미를 정의하는 스마트 포인터를 전달하거나 값으로 반환합니다 (이는 아마도 최상의 솔루션입니다). RVO와 NRVO는 가치의 비용을 아무 것도 복사하지 않기 때문에 –

1

new을 사용하여 메모리를 할당하면 "걱정하지 마십시오. 내가하는 일을 알고 있습니다.이 객체는 나를 제어 할 것입니다". 즉, 컴파일러는 실제로 걱정할 필요가 없으며 사용자가 담당하게됩니다. 가장 좋은 해결책은 : 자신이하는 일을 정말로 알지 못하는 한 그것을하지 마십시오. 참고로, 나는 내가 뭘하는지 알면서도 여전히 일반적으로는 쓸데 없기 때문에 new을 사용하지 않습니다. 당신의 예에서

, 당신은

Object foo() { 
    Object a; 
    // do something 
    return a; 
} 

가 개념적으로, 객체가 스택에 생성하고이 반환 될 때 복사됩니다 사용하고 싶습니다. 복사가 완료되면 로컬 객체가 소멸됩니다. 실제적으로 이것은 실제로 일어나는 일은 거의 없습니다. 복사 한 직후에 로컬 객체가 파기되기 때문에 컴파일러는 평상시에 원하는대로 할 수 있습니다. 객체 a은 복사되거나 소실되지 않지만 실제로 직접 반환됩니다. . 그러나 이것은 동일한 결과를 가져와야합니다 (그렇지 않으면 클래스가 어딘가에서 깨졌습니다).

+0

메서드 스택에서 객체를 반환한다는 것을 의미합니까? 이것은 어떤 시점에서 객체가 덮어 쓰기된다는 것을 의미하지 않습니까? – user1096294

+1

컴파일러가 복사본을 삭제할 때, 컴파일러는 수행중인 작업을 알고 수명이 끝나면 덮어 쓰지 않습니다. 함수에서 반환 한 객체는'new'로 할당 한 객체의 복사본입니다 (그리고'new'ed 객체는 객체를 처리하는 어딘가에 등록되지 않으면 아마도 유출됩니다). –

3

할당 한 개체를 반환하지 않기 때문에 메모리가 누출됩니다. 그러나 복사본이 있습니다. 가장 쉬운 해결책은 당신이 정말로 힙, 예를 들어,에 객체가 필요한 경우 모든

Object foo() { 
    Object a; 
    return a; 
} 

에서 새로운 사용하지 않는 것입니다이 다형성 객체이고 END_LINK하면 관심있는 기본 클래스에 대한 포인터를 반환하는 경우는

Base* foo() { 
    Base *a = new Derived(); 
    return a; 
} 

과 같을 것이다하지만이 코드는 좋은 거리가 멀다. 메모리 누수로 이어질 수있는 예외적 인 저장이 아닙니다. 따라서 거의 항상 std :: unique_ptr (C++ 11 만), std :: auto_ptr 또는 boost :: shared_ptr과 같은 스마트 포인터로 새 코드를 래핑해야합니다.

std::unique_ptr<Base> foo() { 
    std::unique_ptr<Base> a(new Derived(); 
    return a; 
}