rvalue 참조로 반환하는 것이 더 효율적입니까?


133

예를 들면 다음과 같습니다.

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

답변:


246
Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

이것은 lvalue 참조 사례와 마찬가지로 매달려있는 참조를 반환합니다. 함수가 반환되면 임시 객체가 소멸됩니다. Beta_ab다음과 같이 값으로 반환해야합니다.

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

이제 임시 Beta_ab객체를 함수의 반환 값 으로 올바르게 이동 합니다. 컴파일러가 RVO (반환 값 최적화)를 사용하여 이동을 완전히 피할 수 있습니다. 이제 다음을 할 수 있습니다

Beta_ab ab = others.toAB();

그리고 임시로 ab를 구성하거나 RVO를 수행하여 이동 또는 복사를 생략합니다. 문제와 (N) RVO가 어떻게 상호 작용하는지 설명하는 BoostCon09 Rvalue References 101 을 읽으 십시오 .


다른 경우에는 rvalue 참조를 반환하는 것이 좋습니다. getAB()일시적으로 자주 호출 하는 기능이 있다고 상상해보십시오 . rvalue 임시에 대한 const lvalue 참조를 리턴하는 것은 최적이 아닙니다. 이처럼 구현할 수 있습니다

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

참고 것을 move때문에이 경우, 선택하지 ab로컬 자동이나 일시적인를 rvalue도 아니다. 이제 참조 한정자 && 는 rvalue 임시에서 두 번째 함수가 호출되어 복사 대신 다음과 같이 이동한다고 말합니다.

Beta_ab ab = Beta().getAB();

51
나는 항상 리턴 타입이 r- 값 참조 일 때 매달려있는 참조 문제가 자동으로 사라 졌다고 가정했습니다. 그것이 나를 물기 전에 곧게 펴서 다행입니다. 스택 스매싱 버그가 빨라집니다.
deft_code

31
:) 실제로, rvalue 참조는 lvalue 참조와 같이 "그냥 참조"입니다. 그들은 아무것도 복사하거나 저장하지 않습니다.
Johannes Schaub-litb

9
멤버의 const & 한정자는 단순한 const 이상의 기능을 무엇입니까?
galinette


3
@galinette 이들은 참조 규정 자 입니다.
Malcolm

2

그것은 수 있습니다 약간 다른 맥락에서, 예를 들어, 더 효율적일 수 :

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

흥미로운 관찰로, 내 컴퓨터에서 clang++ -O3위의 코드에 대한 54 개의 명령어와 regular에 대한 62 개의 명령어를 생성 std::min합니다. 그러나 -O0이를 사용하면 위의 코드에 대해 518 개의 명령어를 생성하고 regular에 대해서는 481 명령을 생성 std::min합니다.


나는 당신의 대답에 혼란스러워합니다. 비슷한 (아마도) 버전을 시도했지만 실패했습니다 : ideone.com/4GyUbZ 이유를 설명해 주시겠습니까?
Deqing

for(:)할당 해제 된 개체에 대한 임시 개체 와 통합 에 대한 참조를 사용했습니다 . 수정 : ideone.com/tQVOal
wonder.mice

3
이 답변이 실제로 틀리지 않습니까? T, T 매개 변수 템플릿 &&입니다 되지 는 R 값의 기준이 아니라 보편적 인 기준, 그 경우에, 우리가해야 항상 호출 표준 : 앞으로 <T>를 하지 표준 : 이동! 말할 것도없이,이 답변은 위에 투표 한 것과 직접적으로 모순된다는 것입니다.
xdavidliu

@ xdavidliu이 답변은 rvalue로 반환하는 것이 더 효율적일 수있는 방법에 대한 예입니다. std::move()요점을보다 명확하게 설명하기 위해 명시 적 캐스트로 사용됩니다. 프로젝트에 복사하여 붙여 넣을 코드는 아닙니다. 함수 내에 임시 개체가 만들어지기 때문에 최상위 투표 답변과 모순되지 않습니다. 여기에서 반환 된 객체는 인수 중 하나입니다 (임시 객체는 생성 된 지점을 포함하는 전체 표현을 평가하는 마지막 단계로 소멸됨).
wonder.mice

2
@ wonder.mice 그런 다음 T를 std :: string으로 바꾸십시오. 여기서는 템플릿을 사용할 필요가 없으며, T &&를 r- 값 참조로 사용하는 것은 템플릿과 r- 값을 처음 접하는 사람들을 불필요하게 혼란시키는 끔찍한 스타일 일뿐입니다.
xdavidliu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.