2013-09-22 3 views
8

그래서 저는 항상 C++ 포인터에 비해 약간 퍼지 려합니다. 다른 하나는 무엇이든 호출됩니다. 마찬가지로,스택 변수를 반환 하시겠습니까?

Object* pointer = new Object(); 

Object notpointer(); 

내가 포인터는 아마 두 번째에 참여하는 것을 알고 있지만, 기본적으로는하지 포인터입니다. (이것은 실제로 무엇이라고?)

은 또한, 나는 오른쪽 첫 번째를 들어, 당신이 그것으로 완료되면 어느 시점에서

delete pointer; 

를 호출 할 필요가 있다고 생각? 그리고 다른 하나는 걱정할 필요가 없습니다. 첫 번째는 힙에 할당되지만 두 번째는 스택에 할당되고 메서드가 반환되면 사라지는 것을 읽었습니다.

그러나 함수에서 뭔가 (원시가 아닌)를 반환하면 어떨까요?

좋은 예는 Should I return std::strings?로 작성 :

내가 이전에, 문자열 스택에 할당 쓰고, 해제되어야 하는지를으로
std::string linux_settings_provider::get_home_folder() { 
    return std::string(getenv("HOME")); 
} 

때 함수가 반환, 그렇지? 그러나 아무도 그것에 대해 아무 말도하지 않아, 나는 그것이 잘 작동한다고 가정합니다. 왜? 일반적으로

,

return new std::string("pointer"); 

return std::string("not-pointer"); 

의 차이는 무엇인가?

두 작품 모두를 가정 할 때, 두 작품의 장단점은 무엇입니까?

+1

두 번째 기능입니다. – chris

+0

여기에 몇 가지 개념을 혼합하고 있습니다. 포인터는 메모리 주소를 저장할 수있는 변수 일뿐입니다. 'new std :: string'은 메모리 할당과 객체 생성을 수행합니다. 이 두 가지를 함께 사용할 필요는 없습니다. 현대 C++에서는 일반적으로이 작업을 수행하지 않습니다. – greatwolf

+0

문자열이 스택에 할당됩니다. 그것은 ** ** 해제되지 않았습니다. 파괴되었다. 그러나 컴파일러는이를 파기하기 전에 복사합니다. –

답변

11

포인터로 돌아 왔을 때 동적으로 할당 된 객체를 표시하는 방식으로 반환해야합니다 (즉, 나중에 참조 해제되는 경우 스택 객체에 대한 포인터를 반환하면 정의되지 않은 동작이 발생 함). 이는 사용자가 지적한 것처럼 해당 객체를 명시 적으로 삭제해야하기 때문에 메모리 누수가 발생할 수 있습니다.

당신이 반환 값을받는 객체로 반환하면 스택 객체에서 반환 객체를 복사 결과 (두 번째 조각, 즉) 다른 한편으로는, 값으로 반환 :

std::string res = get_home_folder(); // std::string gets copied into res 

컴파일러 return value optimization을 통해 복사하지 않으려면이 값을 최적화 할 수 있습니다.

+0

@BenjaminLindley 네 말이 맞아, 그렇지 않다. 감사! – dasblinkenlight

+0

감사합니다. 그래서, 포인터가 아닌 변수를 무엇이라고 부릅니까? – Erhannis

+0

@Erhannis Correct, 첫번째 스 니펫의'res'는 포인터가 아닙니다. – dasblinkenlight

1

실제로는 Object notpointer();을 쓰고 싶지 않았습니다. notpointer이라는 함수가 실제로 Object을 반환한다고 선언했기 때문입니다. Object notpointer;을 의미한다면 해당 사업체는 으로 전화하십시오. 값은 실제로 스택에 할당되거나 객체의 멤버가 될 때 객체에 포함됩니다.

아무 것도 반환 할 때 반환되는 엔터티는 실제 반환 값이 필요한 위치로 복사되거나 이동됩니다. 반환 값이 구성되면 로컬 객체, 즉 스택에있는 객체가 범위를 벗어나 파괴됩니다.어쨌든 로컬 객체가 사라지는 것을 감안할 때, 컴파일러는 복사 생성자 및/또는 소멸자가 부작용을 가지고 있어도 복사본을 제거하고 올바른 위치에 바로 객체를 구성 할 수 있습니다. 당신은 힙에 할당 된 개체를 얻을 당신이 객체에 대한 포인터를 반환 new std::string("pointer")을 사용할 때 두 개의 리턴 문 사이에

의 차이는

  1. 입니다. 그것은 그 포인터를 누설하는 것은 매우 간단하고, 예를 들어, 적절한 객체로 즉시 std::unique_ptr<std::string> 넣어 더 좋을 것 :

    return std::unique_ptr<std::string>(new std::string("pointer")); 
    

    이 방법을 포인터가 유출되지 않습니다. 물론 std::string* 대신에 반환 유형을 std::unique_ptr<std::string>으로 변경하십시오. 힙 할당은 일반적으로 상당히 비쌉니다.

  2. std::string("value")을 사용하는 경우 로컬 변수 만 반환합니다. 사본이 생략되고 반환 값이 이동해야하는 위치에 즉시 구성 될 수있는 좋은 기회가 있습니다. 관련된 모든 객체가 자동으로 삭제되므로 리소스를 살펴볼 필요가 없습니다. 명시 적 힙 할당은 없으며 스택 할당은 매우 빠릅니다.

물론 주어진 예에서 std::string은 실제로 두 경우 모두 내부 표현을 할당해야합니다. 포인터가 반환되면 추가 내부 할당이 없음을 보장합니다. 반면에 std::string 값을 반환하고 실제로 복사해야하는 경우 내부 메모리를 복사본에 할당해야 할 수 있습니다. 즉, 많은 양의 메모리 할당을 필요로하는 대형 객체를 반환 할 때 값을 반환하는 접근 방식은 복사해야하는 위험을 초래합니다. 그러나 현재의 C++에서는 최악의 경우에 객체가 이동합니다. 즉, C++ 03 에서처럼 객체를 복사하는 것에 대한 걱정이 없습니다.

+0

죄송합니다; 나는'std :: string text ("notpointer");가'std :: string'을위한 1- 매개 변수 생성자라고 불렀고'Object obj();'에 대한 0- 매개 변수 생성자는' . 명백하게. – Erhannis

관련 문제