2016-12-01 1 views
2

std::move의 다음 사례가 불필요한가요? std :: move의 다음과 같은 경우가 불필요한 것입니까?

std::string member; 

obj(std::initializer_list<std::string> p_list) 
    : member {std::move(join(p_list))} 
{} 

조인 기능입니다 :

std::string join(string_initializer_list p_list) { 
    size_t size {}; 
    for (auto const & s : p_list) { 
     size += s.size(); 
    } 
    std::string output; 
    output.reserve(size); 
    for (auto const & s : p_list) { 
     output.append(s); 
    } 
    return output; 
} 
+0

'가입'이란 무엇입니까? – ildjarn

+0

나는 질문을 편집했다;) –

+0

어떤 시나리오에서 std :: move가 유용할까요? –

답변

4

아니요, 너는 std::move이 필요하지 않습니다. std::move의 기능은 임의의 값을 rvalue로 변환하는 것입니다. 함수는 이미 rvalue를 반환하므로 캐스팅은 참조에 대한 결과를 바인딩하는 데 영향을 미치지 않습니다 (이는 기수로부터 member을 초기화하기 위해 수행 한 것입니다). 생략은 join의 리턴 된 객체가 직접적으로 구성된 것을 의미 복사 첫번째 형태에서

std::string s = join({});    // construct from prvalue, elidable, 
             // elision mandatory in C++17 

std::string s = std::move(join({})); // temporary object must be constructed, 
             // s is initialized by moving from the 
             // temporary 

, std::string s = join({}); : std::move을 사용하여 실제로

는 적극적 복사본 생략 억제하므로 엄격한 pessimization 인 s의 장소 (임시 오브젝트가 생성되지 않고 복사 또는 이동이 이루어짐), 또한 함수 본문에있는 output 변수가 생략되어 리턴 값으로 직접 구성됩니다 (즉, s). std::move을 사용하면 첫 번째 elision 단계를 사용할 수 없습니다.

+0

이 경우 실제로 RVO가 손상 될 수 있습니다. 맞습니까? – erip

+0

@erip : 아니요. 다른 상황입니다. 함수 본문에서'return std :: move (output)'이라고 말하면됩니다. 흥미롭게도, 그 주장은 그 반대로 생각됩니다 :'출력 '은 실제로는 좌변 값이지만, 특별한 마법의 이유로 그것은 실제로 그 상황에서 우위로 취급됩니다. –

+0

아, 죄송합니다. :) 답변 주셔서 감사합니다! 고맙습니다. – erip

3

당신의 join 기능이 제정신이고, 예, std::move가 불필요한 것, std::string 반환을 감안할 때; join에서 반환 값은 이미 r 값입니다. 넘어

, w/std::move O는 생략이 std::move을 사용하여 다음 임시 파괴, member를 초기화 이동 생성자, 그것은 임시 string을 강제 호출 할 수하면서, std::move 않고 ​​대신에 그 결과를 만들 수 있음을 의미 복사; 많은 일을하지 않고 (대부분 포인터 복사본을 몇 개 만듭니다),하지만 당신이해야 할 일보다 많습니다.

+0

나는 join 함수를 보여주기 위해 질문을 편집했다;) –

+0

@DagobertoPires : 그리고 내 문장에 대한 자격을 제거하는 대답을 편집했다. :-) – ShadowRanger

+0

어떤 시나리오에서 std :: move가 유용할까요? 나는 이것에 대해 궁금해. –

0

값을 반환하여 rvalue를 반환하는 함수는 std :: move가 적용될 필요가 없으며 다른 사람들이 이미 성능 최적화에 불리한 점을 지적했기 때문에 명확하게 나타냅니다.

예컨대

SomeClass fn() 
{ 
... 
} 

// Move not needed, detrimental, as the function result is already an rvalue 
SomeClass x = std::move(fn()); 

은 11 C++ 전에 평소와 같이 이렇게 : 일반적으로 사용 표준을 말하기

SomeClass x = fn(); 

:: 이동 (x)는 x는 이름이있는 경우. 예를 들어 식별자입니다. 특수한 상황을 제외하고는 일시적으로 유용하지 않습니다 (예 : 복사 방지를 원하지 않는 경우)

참고 : 또한 std :: move로 이동하지 마십시오. "강력한 예외 보장"을 강요하십시오 (예를 들어 잠재적 예외 상황에 직면하여 구조체가 완전히 복사되거나 그대로 남아 있기를 원할 때). 이동 된 유형에 따라 std :: move가 발생할 수 있으므로이 유형의 예외 정책은 아래에 변화. 대신 컴파일 타임에 noexcept와 결합 된 정적 어설 션과 함께 래퍼 함수를 ​​사용하십시오. Is there facility for a strong guaranteed exchange in C++

관련 문제