2013-01-23 6 views
5

임시 변수를 이해할 때 다음 코드가 작동해야하지만 그렇지 않습니다.C++ temporary - "순수 가상 메서드"

struct base 
{ 
    virtual~base() {} 
    virtual void virt()const=0; 
}; 
struct derived:public base 
{ 
    virtual void virt()const {} 
}; 

const base& foo() {return derived();} 

int main() 
{ 
    foo().virt(); 
    return 0; 
} 

virt()를 호출하면 "순수 가상 함수 호출"오류가 발생합니다. 왜 그런가요, 어떻게해야합니까?

답변

5

const 임시 파일의 수명이 연장 될 것으로 예상됩니다. 이것이 발생하지 않는 특정 상황이 있습니다. 이러한 상황 중 하나는 임시 복귀 할 때, 기준이 임시로 결합 된 경우

[임시 변수는 전체 표현의 단부가 아닌 다른 지점에서 파괴되는 제 2 컨텍스트이다. 임시은 어떤 기준을 결합하거나 일시적으로 그 레퍼런스 제외 기준의 수명 동안 지속 바인딩되는 하위 객체의 전체 목적되는 :

[...]

  • 함수 return 문 (6.6.3)에서 반환 값에 대한 임시 바인딩의 수명은 연장되지 않습니다. return 문에서 전체 식의 끝 부분에서 임시가 삭제됩니다.

좌변 투를 rvalue 변환을 필요로합니다 foo()에 의해 반환되는 객체의 멤버 함수를 호출하고 객체 (유형 base에서 파생되지) 유효하지 않습니다, 당신은 정의되지 않은 동작 얻을 수 있기 때문에 :

glvalue를 참조하는 객체가 T 유형의 객체가 아니며 T에서 파생 된 유형의 객체가 아니거나 객체가 초기화되지 않은 경우이 변환이 필요한 프로그램에서 정의되지 않은 동작이 발생합니다.

8

이 소멸되는 임시 참조를 반환합니다.이 함수는 return 문 끝에 함수 을 끝내면 정의되지 않은 동작을합니다.

일시적인 참조를 반환 할 수 없으며 값으로 base을 반환하면 조각이 나게되므로이 기능이 실제로 작동하려면, std::unique_ptr<base>을 반환해야합니다.

+0

가상 테이블도 정리 될 것이기 때문에 ... 따라서 메시지. –

+2

@DougT .: "정의되지 않은 동작"에는 "때문에"가 없습니다. (그 외에도 가상 테이블 *은 결코 "정리"되지 않습니다.) –

+0

virt()가 반환 된 후 전체 표현식의 끝에서 임시 객체가 삭제되지 않아야합니까? – Dave

3

그런 개체에 대한 참조를 반환 할 수 있다고 생각하지 않습니다. 파생 된() 인스턴스는 foo()가 리턴하자마자 범위를 벗어납니다. 작동해야

base *foo() { return new derived(); } 

foo()->virt(); 

있습니다.

+3

이 작업은 가능하지만 요즘에는 원시 포인터를 전달할 필요가 없습니다 ... –

+2

shared_ptr <> 또는 기타를 사용하려면 실제 코드에서 수행해야합니다. 그러나 요점은 근본적으로 우리가 힙에 객체를 할당하여 포인터가 두려워서 왜 그 사실을 숨길 수 있는지를 알아 내야한다는 것입니다. – Johannes

+1

@Johannes : 그냥 메모리 누수가 필요하기 때문입니다. 스마트 포인터가 표준 라이브러리에 있습니다 - 사용하십시오! : -] – ildjarn

0

호출하는 동안 개체가 없으므로 로컬 개체가 삭제되었습니다. 보아야 할 vtable이 없습니다. 시도 :

base& foo() { return *new derived(); } 
+0

호출자는 메모리를 확보해야한다는 것을 어떻게 알 수 있습니까? –

0

임시 '유도 (derived)'개체가 스택에 할당됩니다. 객체 상향 조정과 관련이있을 수 있습니다.

CONST베이스 & foo는() {유래 * D = 새로운 파생(); return * d; }

잘 작동합니다.

class A { 
public: 
    const base &foo() { return d; } 
private: 
    derived d; 
}; 

이 방법은 파생 된 개체의 수명이 A의 수명만큼, 그리고 어떤 문제가 없을 것 :

+1

메모리 누수가 잘 작동하지 않습니다. ; -] – ildjarn

+0

잡아 주셔서 감사합니다. boost :: shared_ptr <>을 사용할 수 있습니다. – Arcturus

0
이에 문제 조각을 변경

.

+0

함수'bar' 스택에 A를 생성하고'bar'에서'd'에 대한 참조를 반환하면 어떻게됩니까? –

관련 문제