developer tip

C ++ 지역 변수에 대한 참조 반환

copycodes 2020. 8. 16. 20:59
반응형

C ++ 지역 변수에 대한 참조 반환


i를 반환해야하는 경우 다음 코드 (func1 ())가 정확합니까? 지역 변수에 대한 참조를 반환 할 때 문제가 있다는 것을 읽은 것을 기억합니다. func2 ()와 어떻게 다릅니 까?

int& func1()
{
    int i;
    i = 1;
    return i;
}

int* func2()
{
    int* p;
    p = new int;
    *p = 1;
    return p;
}

이 코드 조각 :

int& func1()
{
    int i;
    i = 1;
    return i;
}

수명이 함수 호출 범위로 제한된 객체에 대한 별칭 (참조)을 반환하므로 작동하지 않습니다. func1(), int i이제는 존재하지 않는 객체를 참조하기 때문에 함수에서 반환 된 참조를 쓸모 없게 만듭니다.

int main()
{
    int& p = func1();
    /* p is garbage */
}

두 번째 버전은 변수가 함수 호출의 수명에 제한되지 않는 무료 저장소에 할당되기 때문에 작동합니다. 그러나 delete할당 된 int.

int* func2()
{
    int* p;
    p = new int;
    *p = 1;
    return p;
}

int main()
{
    int* p = func2();
    /* pointee still exists */
    delete p; // get rid of it
}

일반적으로 포인터를 일부 RAII 클래스 및 / 또는 팩토리 함수로 래핑하여 delete직접 수행 할 필요가 없습니다 .

두 경우 모두 값 자체를 반환 할 수 있습니다 (제공 한 예제가 아마도 인위적 이었음을 알고 있습니다).

int func3()
{
    return 1;
}

int main()
{
    int v = func3();
    // do whatever you want with the returned value
}

func3()오늘날 거의 모든 컴파일러가 어떤 형태의 반환 값 최적화를 구현하기 때문에 동일한 방식 으로 원시 값을 반환 하는 방식으로 큰 객체를 반환하는 것이 좋습니다 .

class big_object 
{ 
public:
    big_object(/* constructor arguments */);
    ~big_object();
    big_object(const big_object& rhs);
    big_object& operator=(const big_object& rhs);
    /* public methods */
private:
    /* data members */
};

big_object func4()
{
    return big_object(/* constructor arguments */);
}

int main()
{
     // no copy is actually made, if your compiler supports RVO
    big_object o = func4();    
}

흥미롭게도 임시 참조를 const 참조에 바인딩하는 것은 완벽하게 합법적 인 C ++ 입니다.

int main()
{
    // This works! The returned temporary will last as long as the reference exists
    const big_object& o = func4();    
    // This does *not* work! It's not legal C++ because reference is not const.
    // big_object& o = func4();  
}

A local variable is memory on the stack, that memory is not automatically invalidated when you go out of scope. From a Function deeper nested (higher on the stack in memory), its perfectly safe to access this memory.

Once the Function returns and ends though, things get dangerous. Usually the memory is not deleted or overwritten when you return, meaning the memory at that adresss is still containing your data - the pointer seems valid.

Until another function builds up the stack and overwrites it. This is why this can work for a while - and then suddenly cease to function after one particularly deeply nested set of functions, or a function with really huge sized or many local objects, reaches that stack-memory again.

It even can happen that you reach the same program part again, and overwrite your old local function variable with the new function variable. All this is very dangerous and should be heavily discouraged. Do not use pointers to local objects!


A good thing to remember are these simple rules, and they apply to both parameters and return types...

  • Value - makes a copy of the item in question.
  • Pointer - refers to the address of the item in question.
  • Reference - is literally the item in question.

There is a time and place for each, so make sure you get to know them. Local variables, as you've shown here, are just that, limited to the time they are locally alive in the function scope. In your example having a return type of int* and returning &i would have been equally incorrect. You would be better off in that case doing this...

void func1(int& oValue)
{
    oValue = 1;
}

Doing so would directly change the value of your passed in parameter. Whereas this code...

void func1(int oValue)
{
    oValue = 1;
}

would not. It would just change the value of oValue local to the function call. The reason for this is because you'd actually be changing just a "local" copy of oValue, and not oValue itself.

참고URL : https://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable

반응형