2012-04-01 8 views
18

내가이 이루어 코멘트에 이어 xvalues ​​:있습니까 반환 지역 주민이 자동으로

passing std::vector to constructor and move semantics 다음 코드에서 필요한 std::move가, 반환 값이가 xValue 있는지 확인하기 위해?

std::vector<string> buildVector() 
{ 
    std::vector<string> local; 

    // .... build a vector 

    return std::move(local); 
} 

이것이 필요하다는 것은 이해할 수 있습니다. 나는 종종 함수에서 std::unique_ptr을 반환 할 때이 사용 보았다, 그러나 GManNickG는 다음과 같은 코멘트를했다 : 그것은 return 문에서 모든 지역 변수가 자동 것을 나의 이해는

xvalues입니다 (값을 만료)와 이동합니다 ,하지만 그 경우에만 반환 된 개체 자체에 적용되는지 확실하지 않습니다. 그래서 OP는 앞으로 나아가 야 할 때까지해야한다고 확신 할 때까지 거기에 넣어야합니다. :)

std::move이 필요한 경우 누구에게 알 수 있습니까?

동작 컴파일러는 종속적입니까?

+0

주 당신이 날 이후 내 문을 수정하기 위해 발생했습니다


당신에게 그게 무슨 뜻인지에 대한 간단한 예제를 제공합니다. 이동 된 반환 값 (로컬 변수 일 수 있음)이며 일반적으로 모든 로컬 변수가 아닙니다. (그것이 좋을지라도, 나는 생각할 수없는 오래된 코드를 깨뜨릴 것이고, C++ 진행은 이전 버전과의 호환성을 유지해야한다.) – GManNickG

답변

14

귀하는이 상황에서 local이 rvalue로 반환된다는 것을 보장합니다. 일반적으로 컴파일러는 반환 값 최적화를 수행하기도하지만 문제가되기 전에는 local 객체가 호출 사이트에서 직접 생성되므로 실제 이동이 전혀 표시되지 않습니다.

관련성 높은 참고 6.6.3 [ "return 문"(2) :는 r- 수치 간주 복귀 생략 될 수 문 또는 와 연관된

카피 또는 이동 동작 생성자 선택에서 과부하 해결을 위해 (12.8).

사실 명확하게 말하면 반환 된 객체는 로컬 객체에서 이동할 수 있습니다 (실제로 RVO가이 단계를 완전히 건너 뛸지라도). 표준의 규범적인 부분은 12.8 절 ("클래스 객체 복사 및 이동") (31, 32), 복사 elion 및 rvalues ​​(감사합니다 @Mankarse!)입니다. 실제를 rvalue 참조를 반환과

#include <utility> 

struct Foo 
{ 
    Foo()   = default; 
    Foo(Foo const &) = delete; 
    Foo(Foo &&)  = default; 
}; 

Foo f(Foo & x) 
{ 
    Foo y; 

    // return x;   // error: use of deleted function ‘Foo::Foo(const Foo&)’ 
    return std::move(x); // OK 
    return std::move(y); // OK 
    return y;   // OK (!!) 
} 

명암이 :

Foo && g() 
{ 
    Foo y; 
    // return y;   // error: cannot bind ‘Foo’ lvalue to ‘Foo&&’ 
    return std::move(y); // OK type-wise (but undefined behaviour, thanks @GMNG) 
} 
+0

+1 (마지막으로 UB가 있고 형식 검사 예제로만 살펴야 함) – GManNickG

+0

@GManNickG : True; 당신은'forward'와'move'를 제외하고는 실제로 &&'를 반환하지 않습니다. 그것은 인위적인 예입니다. –

+0

이 동작을 보장하는 규범적인 단락은'[class.copy]/32'입니다. – Mankarse

4

내가 대답은 전혀 생각하지


여기에 바보 같은 예입니다.이 경우

표현식이가 xValue입니다 : 공식적으로 만 참고하지만,/6 §5는 표현이 xvalues ​​/없는 무엇을 요약

  • 함수를 호출 한 결과, 암시 적 여부 반환 유형이 객체 유형에 대한 참조 값 인
  • 객체 유형에 대한 값을 참조로 캐스트
  • 비표준 유형의 비 정적 데이터 멤버를 지정하는 클래스 멤버 액세스 표현식 개체 표현이 x 값이거나
  • 입니다.
  • . * 첫 번째 피연산자가 xvalue이고 두 번째 피연산자가 데이터 멤버에 대한 포인터 인 멤버 포인터 식 표현식입니다.

일반적으로이 규칙의 효과는 명명 된 rvalue 참조가 lvalues로 처리되고 개체에 대한 명명되지 않은 rvalue 참조가 xvalues로 처리된다는 것입니다. 함수에 대한 rvalue 참조는 이름이 지정되었는지 여부에 관계없이 lvalues로 처리됩니다.

첫 번째 요지가 여기에 적용되는 것 같습니다. 문제의 함수가 rvalue 참조가 아닌 값을 반환하기 때문에 결과는 x 값이 아닙니다.

+0

+1이 xvalues에 대해 이야기하기 때문에, 내가 거기에서도 틀렸기 때문입니다. (내 하루는 아니 겠지요.) 다행히도, 정말로 중요한 점은 반환 값을 rvalue로 처리 할 수 ​​있다는 것입니다. 하지만 내가 주장한 것처럼 일반적으로 모든 xvalues. – GManNickG

7

어쨌든 return std::move(local)return local은 모두 컴파일한다는 의미에서 작동하지만, 동작이 다릅니다. 그리고 아마 후자의 것만이 의도되었습니다.

std::vector<string>을 반환하는 함수를 작성하는 경우 std::vector<string>을 반환해야합니다. std::move(local)의 유형은 std::vector<string>&&이고 이 아닌std::vector<string>이므로 이동 생성자를 사용하여이 형식으로 변환해야합니다.

이 표준은 6.6.3.2에서 말한다 : 식의

값은 암시 적으로 이이 나타나는 함수의 리턴 유형으로 변환 할 수 있습니다. return local 만이 당신에게 하나의 작업을 아끼지

return local; // not yet a copy constructor call (which will be elided anyway) 

반면 의미

, return std::move(local)

std::vector<std::string> converted(std::move(local); // move constructor 
return converted; // not yet a copy constructor call (which will be elided anyway) 

에 equalvalent된다.

struct test { 
    test() { std::cout << " construct\n"; } 
    test(const test&) { std::cout << " copy\n"; } 
    test(test&&) { std::cout << " move\n"; } 
}; 

test f1() { test t; return t; } 
test f2() { test t; return std::move(t); } 

int main() 
{ 
    std::cout << "f1():\n"; test t1 = f1(); 
    std::cout << "f2():\n"; test t2 = f2(); 
} 

이 뜻을 출력

f1(): 
    construct 
f2(): 
    construct 
    move 
+0

입력 해 주셔서 감사합니다. – mark

+0

NVRO/elision이있는 경우에만 해당됩니다. elisation이 없다면'f1' 또한 움직여야 할 것입니다. –

+0

@NicolBolas : 그렇습니다. 위에서 작성한 "아직 복사 생성자 호출"부분입니다 (실제로는 생성자 호출이 이동해야합니다). 그러나 이것은'f1'과'f2' 둘 다에 영향을 미치므로'f1'은 하나의 생성자가 less를 호출하도록합니다. – ipc