2014-10-14 2 views
8

내가 읽고 읽은 바로는 rvalue 인 표현식을 lvalue 참조에 바인딩 할 수 없습니다. 그러나 내가 본 것은 rvalue를 rvalue reference에 바인딩 할 수 있고 명명 된 rvalue 참조가 본래 lvalue이므로 lvalue 참조에 바인딩 할 수 있습니다. rvalue를 lvalue 참조에 바인딩 할 수없는 이유는 무엇입니까? 최적화 목적입니까? 당신이 foo(1)를 호출 할 때 1와 같은 임시 int가 생성되고,왜 rvalue를 lvalue 참조에 간접적으로 바인딩 할 수 있습니까?

#include <iostream> 

using std::cout; 

void bar (int& b) { 

    cout << "bar " << b << "\n"; 
    b = 3; 
} 

void foo (int&& a) { 

    cout << a << "\n"; 
    bar(a); 
    cout << a << "\n"; 
} 

int main (int argc, char ** argv) { 

    foo(1); 
} 
+5

언어로 인해 재해를 일으킬 수 있다고해서 언어에 문제가있는 것은 아닙니다. 반면에 lvalue 참조가 rvalues에 바인딩되도록 허용하면 본질적으로 추론 할 수있는 함수를 작성하는 것이 본질적으로 불가능합니다. –

+0

관련 http://stackoverflow.com/questions/2577623/some-clarification-on-rvalue-references –

+0

이전에 (한 번 이상) 질문했습니다. 철저하게 검색하면 중복 된 항목을 찾을 수 있습니다. Stroustrup은 (D & E 나 TC++ PL에서 기억할 수없는) 실수를 막는다 고 말합니다 :'void twice (int & x) {x * = 2; } double x = 1.0; 두 번 (x); // does not modify x' – dyp

답변

9

은 C++의 기본적인 규칙 그리고 그것은 버그 방지 :

int foo(); 

int& x = 3;  // whoops 
int& y = foo(); // whoops (sometimes) 

"를 rvalue 참조"(유형 세트를, 실제 우변와 혼동되지 않음)에서 적어도 만들어진 일부 당신이 정말로 원하는 경우 은 여전히이 작업을 수행 할 수 있도록하기 : 앞의 예에서

int&& x = 3;  // oh, go on then *sigh* 
int&& y = foo(); // you'd better be sure! 

, 나는 빈 rvalue 표현식에 의해 참조 된 객체를 참조로 바인딩 (또는 바인딩 시도)합니다.

지금, 나는 참고로 좌변 식에 의해 명명 된 객체 구속한다 :

int i = foo(); 

int& x = i;  // no problem michael 

을 그리고 있는지 확인 당신 정말는 믿을 수 없을만큼 도입, 좌변 식으로부터를 rvalue 참조를 취득하기위한 것 std::move을 제대로 명 :

int&& x = std::move(i); // doesn't move anything 

이 나중에 규칙은 더 이상 의심 할 여지없이 지난 20 년 동안 많은 버그를 방지 한 원래의 기본 규칙보다 훨씬했다.

Visual Studio는 역사적으로 T& x = bar()을 승인했습니다. 여기서 T은 사용자 정의 형식입니다. 그림을 이동.

+0

'(가끔)'을 설명 할 수 있습니까? –

+0

@Matt :'int & foo() {static int xyzzy = 42; xyzzy를 반환; }'. int foo();가 추가 된 것을 예측합니다. 아마 내가 그것을 제거해야합니다. –

+0

그래서 rvalue 참조가 유형의 카테고리라고하면 lvalue 참조가 유형 카테고리라고 가정합니다. 그래서 그것은 제가 예제에서 bar를 호출 할 때 rvalue reference를 유형이기 때문에 lvalue reference로 변환한다는 것을 의미합니까? 또는 참조되고있는 참조 된 기본 객체가 lvalue 참조로 참조됩니다. – edaniels

0

int&& a가 결합되어

이 예제를 가져 가라. 자유롭게 변경할 수 있습니다. 동일한 방법으로 int&& a = 1;을 작성할 수 있습니다. a 자체가 lvalue이므로 lvalue 참조를이 값에 바인딩 할 수 있습니다.

우월호 및 좌변기 참조를 자세히 설명하는 Scott Meyers의 우수 기사 Universal References을 읽을 수 있습니다.

6

rvalue를 lvalue 참조에 바인딩하지 못하게하는 이유는 무엇입니까?

이 질문에 대한 답변은 귀중하고 주목할만한 출처 인 The Design and Evolution of C++ by Bjarne Stroustrup을 참조하지 않고도 완료 될 수 없습니다.

는 3.7 비얀 쓴다

내가 아닌 const 참조 가 비 좌변에 의해 초기화 할 수 있으므로, 비록 하나의 심각한 실수.예를 들어 : 때문에 int& 이렇게 임시 전달 double 참조 할 수없는 유형의 차이
void incr(int& rr) { rr++; } 

void g() 
{ 
    double ss = 1; 
    incr(ss); // note: double passed, int expected 
       // (fixed: error in Release 2.0) 
} 

ss의 값으로 초기화 된 int 를 유지하기 위해 생성 하였다. 따라서 incr()은 임시 수정되었으며, 결과는 호출 함수에 반영되지 않았습니다.

특히 질문이 많은 이유, 특히 C++ 98 표준 이전에 내려진 규칙과 관련하여 많은 것을 이해하려면 The Design and Evolution of C++을 적극 권장합니다. 유익하고 흥미로운 언어의 역사입니다.

+0

--- 감사 Niall –

관련 문제