2014-12-04 2 views
4

C++ 표준에서는 const 참조를 rvalues에 바인딩 할 수 있으므로 참조가 범위를 벗어날 때까지 임시의 수명이 연장됩니다. 먼저 기능 foo()인지가 무슨 일, 예를 들어 같은 x86 아키텍처를 사용하여, 내가 아는const 참조가 임시로 바인딩 될 때 스택에서 어떤 일이 발생합니까?

std::string foo() { 
    return std::string("foo"); 
} 

void bar() { 
    VeryBigObject obj; 
    // Perhaps do something with the big object 
} 

int main(int, char **) { 
    const std::string &foo_str = foo(); 
    bar(); 
    return 0; 
} 

: 그러나, 나는이 실제로 컴파일하는 방법을 알아낼 수 없습니다, 내가 예와 함께 설명하자 이 문자열 객체는 스택에 구성되며 이는 필요한 공간을 rsp 레지스터에서 뺍니다 (64 비트 아키텍처라고 가정). 이후에 rsp 레지스터가 원래 값으로 반환되어 foo() 함수가 채우는 스택 공간을 확보하고 올바르게 이해하면 bar()에 대한 호출은 해당 스택 공간을 사용하여 VeryBigObject을 구성하여 문자열을 덮어 씁니다.

이 점을 염두에두고 어셈블리 도메인에서 foo()을 호출 한 후 어떻게 문자열의 수명을 연장 할 수 있습니까?

+0

참고 자료에 대한 나의 비공식적 인 이해는 C++ 컴파일러가이를 포인터로 변환한다는 것입니다. – Bathsheba

+0

그것이 당신이 그것을 묘사하는 방식으로 행동한다면 그것은 매우 외설스러운 컴파일러가 될 것입니다. –

+1

@ Bathsheba : 때로는 포인터처럼 구현됩니다. 때때로 (여기처럼) 참조 된 객체는 컴파일러에게 알려 지므로 런타임 간접 지정없이 직접 액세스 할 수있는 코드를 생성 할 수 있습니다. –

답변

6

임시 반환 값은 foo의 임시 프레임을 복사/이동하거나 RVO를 사용하여 복사본을 삭제하고 호출자의 프레임에서 직접 구성하여 스택 프레임 main에 생성됩니다.

참조에 바인딩되면 임시는 참조 기간 동안 지속됩니다. 사실 임시 변수는 동일한 범위의 명명 된 변수와 동일한 방식으로 관리됩니다.

+0

그것이 내가 그것을 이해해야하는 방법입니다. 내 의심의 여지가 RVO는 선택적이지만, 참조가 효과적으로 참조로 작동한다는 것을 보장하는 표준과 함께합니다. 즉, 참조 된 개체가 복사되지 않습니다 **. 이것은 근본적인 컴파일러 구현자가 꼭 결정하지 않더라도 컴파일러가 RVO를 사용하도록 강제합니다. –

+2

@gdasamu : RVO가 없으면 하나의 임시가'foo'의 프레임에서 만들어지고, 그 다음 복사/이동되어'main'의 프레임에서 초를 만들어 함수 호출 결과를 만듭니다. RVO를 사용하면 하나만 '메인'에 직접 생성됩니다. 두 경우 모두, 참조는'main'에있는 것에 바인딩됩니다. –