2010-07-15 3 views
9

나는 답을 모르는 기본적인 질문입니다. 팔로우 기능이 유효합니까?C++ 반환 참조/스택 메모리

std::vector<int> & test_function() { 
    std::vector<int> x; 

    // do whatever 

    return x; 
} 

그렇다면 이유는 무엇입니까? 함수가 반환 된 후 프로그램에서 x를 스택에서 삭제하면 안됩니까? 감사.

답변

11

동작은 정의되지 않습니다. 지역 변수에 대한 참조를 반환하면 안됩니다.

+1

젠장, 저를 이길! – Anthony

+1

표시된 코드는 그 자체로 정의되지 않은 동작을 포함하지 않습니다. UB는이 함수를 호출하는 다른 코드에서 발생합니다. –

8

함수의 형식이 올바르지 만 (구문 상 올바르지 만) 함수가 반환 되 자마자 반환 된 참조는 유효하지 않으므로 사용할 수 없습니다.

명확히하기 : 해당 코드는 이 아니며은 정의되지 않은 동작을 호출합니다. 당신이 반환 값을 사용하지 않는 한 당신은 안전하게 오랫동안이 함수를 호출 할 수 있습니다, 예를 들어,이 유효합니다

test_function(); // ok 

그러나, 당신은 반환 값을 사용하려고하면 (즉, 그것은 또는 사본을 다른 참조를 초기화 지시 대상 (객체 x의 수명)이 종료 한 것이기 때문에 다른 객체로 지시 대상은) 당신은 정의되지 않은 동작을 호출합니다 (x은 그것이 자동 변수) 때문에 함수가 반환 할 때 파괴됩니다

std::vector<int>& vec = test_function(); // undefined 
std::vector<int> vec = test_function(); // undefined 
+0

참고로 참조되는 구조체가 POD (포인터가 없음)의 무리이거나 프리미티브 인 경우 정상적인 스택 프레임이 보유되어 있고 값을 복사하면 (참조를 보유하지 않으므로 두 번째 예를 들어 여기에서) 원래의 지역 값은 반환 다음에 곧바로 괜찮을 것입니다 ('mov esp, ebp; pop ebp;'로컬 스택 프레임은 방해받지 않습니다). 그러나 소멸자가 호출되고 데이터가 조작/변경 될 수 있습니다. 이것은 한 가지 방법으로 정확하게 추측해도 이식성이 없다고 할지라도이 문제를 해결하고 어떤 일이 발생할지 예측하는 잘못된 방법입니다. –

+0

@jMerliN : POD 유형의 객체의 경우에도 결과는 공식적으로 정의되지 않습니다. POD의 수명은 저장 기간이 끝나면 끝납니다. 지역 변수의 경우 함수가 리턴하는 시점에 있습니다. 수명이 끝난 후에 객체를 사용하면 정의되지 않은 동작이 발생합니다. 이것은 아마도 POD 유형의 객체로 실제로 "작동"합니까? 아마도,하지만 당신이 말했듯이, 그것은 의존해야하는 행동이 아닙니다. –

+0

다른 스레드가 이미 스택 프레임의 위치를 ​​재사용했기 때문에 다중 스레드가 표준이 될 때 확실히 의존해서는 안됩니다 (표준에서는 스택 또는 힙 구현 방법을 정의하지 않습니다). –

0

가 poi를 반환 할 수없는 것과 같은 이유로 로컬 변수에 대한 참조를 반환 할 수 없습니다. 함수에서 반환 할 때 해당 지역 변수의 할당이 해제되어 참조 또는 포인터가 유효하지 않게되기 때문에 지역 변수에 연결해야합니다.

2

예, 유효하지만 반환 값을 사용하려고하면 정의되지 않은 동작이 발생합니다.