2013-01-22 3 views
1

에 가능한 중복 쓰기 : 성능의 측면에서
In C++, is it still bad practice to return a vector from a function?반환 문은

함수에서 'return'heavier std::vector 또는 std::string 같은 개체를 필요 , 이 양식을 사용하는 것이 좋습니다. :

void func(std::vector<int> *dest) 
{ 
} 
대신이 양식의

:

std::vector<int> func() 
{ 
    std::vector<int> arr; 
    // ... 
    return arr; 
} 

내가 처음 양식을 빠르게 처리 될 수 있다고 가정하고, 그러나 동시에 나는 자주 두 번째 양식을 본 적이 Qt는 API는 종종 QString 예를 들어 반환 아마 훨씬 더 편리하거나 직관적으로 사용하기 때문일 것입니다.

또한 return 문을 사용할 때 불필요한 객체 복사를 제거 할 수있는 컴파일러 최적화가 있는지 궁금해했습니다.


편집

거기에 어떤 인기있는 컴파일러 여전히 답변에서 언급 한 최적화를 수행하지 않는 오늘날 사용? 값을 기준으로

+0

예, 리턴 값 최적화라고합니다. – chris

+1

읽을 거리가 뭔가요? [원하는 속도? 값으로 전달] (http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) – ipc

+0

http://stackoverflow.com/questions/3134831/in-c-is - 아직도 - 나쁜 - 연습 - 반환 - 벡터에서 함수 –

답변

7

[값으로 돌아 가기] 대신 [포인터로 전달]을 사용하는 것이 좋습니다?

아니오.

A modern C++ compiler performs named return value optimisation (NRVO) 이는 컴파일러가 여기에서 복사본을 안정적으로 삭제한다는 것을 의미합니다. 복사가 수행되지 않습니다.

사용중인 C++ 버전에 관계없이 다음과 같은 점에 유의하십시오. C++ 03은 C++ 11뿐 아니라 C++ 11에도 적용됩니다.C++ 11에서 변경된 유일한 점은 언어가 copy elision을 수행 할 수 없을 때 라이브러리가 효율적으로 값에서 벗어나도록하는 것입니다 ().

반환 값으로는 일반적으로 복사 추출을 수행 할 수 있습니다. 다른 경우에는 더 적절합니다 (예 : 매개 변수를 값으로 전달). 예외가 있습니다. 다음 코드는 명명 된 반환 값 최적화를 사용할 수 없습니다. 그것은 비록 C++ (11) 이동을 사용할 수 있습니다

std::string foo() { 
    std::string one = "Foo"; 
    std::string two = "Bar"; 

    if (rand() % 2 == 0) 
     return one; 
    else 
     return two; 
} 

이유는 이제 두 개의 코드 경로가 다른 명명 된 개체 반환이다; 이것은 NRVO를 방지합니다.

+0

다른 응답에서 C++ 11을 언급 했으므로 이거 전에 잡아? 의미, 그것을 지원하는 C++의 가장 초기 버전입니까? – sashoalm

+0

@satuon 예전에 확실히 그렇습니다. 그러나, 내 대답에 경고를 참조하십시오. –

+1

@ KonradRudolph :하지만 당신의 예제는 RVO를 사용할 수 있습니다. 최적화를 무효화하기 위해 두 개의 다른 std :: string' 변수를 반환하는 예제가 필요합니다. –

3

반환 :

std::vector<int> func(); 

C++는 바로이 같은 상황 복사 생략이 가능하고, 그 이상 새로운 C++는 움직임이 ­ 사람이 그 작업을 저렴하게 ­ 틱 SE는 정의했다. 컴파일러는 일반적으로이 우물을 구현합니다. (복사 생략으로, 해당 지역의 arr 실제로 좋아.이 situa ­ 기도 "반환 값 최적화"로 알려져 수신자 전화 사이트 변수에 건설되고 종료됩니다.) C++ (11)와

1
std::vector<int> func(); 

, 위가 귀하의 기능이어야합니다. 함수가 반환 될 때 로컬 std::vector 개체는 으로 이동합니다. 가능한 경우 도 이동은 컴파일러에서 생략 할 수 있습니다.

즉, 걱정할 필요가 없습니다. 가치로 돌아갑니다.

2

RVO 및 NRVO를 허용하는 규칙은 ARM (1990), 에 있었으므로 컴파일러에서 구현하지 않은 경우에는 놀랄 것입니다.

더 중요한 것은 out 매개 변수 (포인터가 아닌 것 또는 const가 아닌 부분에 대한 참조)를 사용하는 것이 매우 어렵다는 것입니다.반환 값을 복사하기 때문에 실제로 시간 문제가 발생했다는 것을 프로필러가 알릴 때까지 을 입력하십시오. 어떤 시점에서, 이의 라인을 따라,이 함수를 오버로드 : 그런 다음 프로파일 러는 가진 문제는 말한다 위치에, 모두를 시도

void func(std::vector<int>& dest) 
{ 
    // ... 
} 

std::vector<int> func() 
{ 
    std::vector<int> results; 
    func(results); 
    return results; 
} 

및 경우 (문제를 해결 하나를 선택 그것을 차이를 만든다).

나는 실제로 이것을 한 번해야했다. 그러나 그것은 언젠가는 1991 년이나 1992 년경이었습니다. 그 이후로 나는 그것을하지 않아도되고, 마지막으로 몇년 동안, 나는 꽤 좋은 성과를 내고 있습니다. 중요한 사항; 우리는 여전히 std::vector 또는 을 집에 Matrix 클래스로 정기적으로 반환합니다. C++ 11의 이점이 없으면 이 대상 컴파일러 모두에서 지원되지 않기 때문입니다.