programing

std :: move ()를 사용하는 것이 조기 최적화입니까?

nasanasas 2020. 11. 21. 11:18
반응형

std :: move ()를 사용하는 것이 조기 최적화입니까?


다음 코드가 있다고 가정합니다.

int main()
{
    std::vector<std::string> strs;

    std::string var("Hello World");
    // Make some modifications to 'var'
    strs.push_back(std::move(var));
}

제가 지적하고 싶은 샘플 부분은 std::move(). 기본적으로 나는 push_back()전화 사본에 대해 걱정 합니다. 내가 추가하는 문자열이 정말 크다고 가정합니다. 나는 여전히 C ++ 11 r-value 참조를 배우고 있기 때문에 컴파일러가 std::move().

이것이 조기 최적화인지 (일반적으로 복사를 피하고 싶은 모든 경우 강제 이동) 누구든지 설명 할 수 있습니까? 그렇다면 여기에서 최적화되고 자동으로 이동할 수 있도록 컴파일러가 따라야 할 (또는 따라야 할 가능성이 가장 높은) 패턴은 무엇입니까?

편집하다

NRVO / RVO가 적용되기 때문에 함수 반환 값 에서 자동 이동이 어떻게 발생하는지 이해한다고 덧붙이고 싶습니다 . 여기서 제가 제시 한 구체적인 예는 RVO를 적용하지 않을 것이므로 확실하지 않습니다.


다른 답변은 내 취향에 따라 질문의 기술적 측면에 너무 초점을 맞추기 때문에 좀 더 일반적인 답변을 제공하려고 노력할 것입니다.

간단히 말해서 : 아니요, 질문에 설명 된 방식으로 std :: move와 같은 "트릭"을 사용하는 것은 조기 최적화가 아닙니다. 사용하지 않음 std::move이 사용할 수있는 경우 코드가 이미 성능이 중요한 것으로 알려져있다하지 않는 한, 너무 잘된다.

조기 최적화를 피해야하는 필요성은 때때로 "필요하다는 것을 증명할 수있을 때까지 최적화하지 마십시오"로 이해되지만, "해결해야 할 필요가 있다는 것을 알지 못하는 한 문제 해결에 시간을 낭비하지 마십시오"라고 읽는 것을 선호합니다.

조기 최적화는 최적화 할 필요가없는 것을 최적화하기 위해 노력을 기울여야하며 일반적으로 그렇게하면서 단순한 문제를 복잡한 문제로 변환합니다. 그런 관점에서 나는 질문 자체에 대한 오랜 숙고를 조기 최적화로 분류 할 것입니다.

관련 예 : 성능이 중요한 코드에서 작업하는 사람들은 종종 인수를 const 참조 ( const std::string&) 로 전달 합니다. 그것이 그들이 사용하는 일이기 때문에 그들은 단지 pass-by-copy ( const std::string또는 심지어 std::string)를 사용할 수 있더라도 성능이 중요하지 않은 코드에서 동일한 패턴을 사용합니다 . 그것은 조기 최적화도 아닙니다.


컴파일러가 .NET Framework없이 복사본을 최적화하는 방법을 모르겠습니다 std::move().

매우 영리한 컴파일러 만이이를 최적화 할 수 있으므로 복사본이 비쌀 수 있다면 (예 : 매우 긴 문자열) 이동하는 것이 좋습니다.

이동하지 않으면 코드는 효과적으로 다음을 호출하는 시퀀스입니다.

strlen  // count "Hello World"
malloc  // allocate memory for string var
strcpy  // copy data into var
malloc  // re-allocate vector
free    // deallocate old vector
malloc  // allocate new string
strcpy  // copy from var to new string
free    // destroy var

이동하면 다음과 같이됩니다.

strlen  // count "Hello World"
malloc  // allocate memory for string var
strcpy  // copy data into var
malloc  // re-allocate vector
free    // deallocate old vector

이론적으로 스마트 컴파일러는 자동으로 변환을 할 수 있지만, 컴파일러는 생성자와 소멸자와 도입 추상화의 모든 레이어를 통해 볼 수 있도록 할 수 vector멤버 함수 때문에 코드가 제거로 변환 될 수 있다는 것을 증명하는 매우 어려운 malloc하고 free있다 복잡한.


이후 std::move에 원래 객체 (이 경우 var)는 유효한 상태 여야하지만 값을 보유 할 수 있습니다 (예 : 비어있을 수 있음).

당신이 사용하지 않을 것이라는 것을 알고 있고 당신이 var그것을 만들기 위해서만 만들었 vector다면 그것은 당신이하려고하는 것의 의도로서 정말로 "조기"최적화가 아닙니다.

vectoremplace_back()똑같지 만 더 명확한 새로운 방법 가지고 있으며 앞으로 인수를 사용합니다 (여기서는 emplace_back("Hello World")당신이하고있는 모든 것이 그것을 구성하는 경우 에만 수행 합니다). 귀하의 경우 "var로 일부 수정"하는 emplace_back것은 적절하지 않을 것입니다.

예전 에는 빈 문자열에 대해 C++수행 push_back()한 다음이를 교체 하여 복사본을 최적화 할 수있었습니다 .


왜 모든 사람들이 emplace_back(). 의 목적은 emplace_back()개체를 제자리에 구성하여 복사 / 이동 작업을 방지 하는 것입니다 . 이 경우 이미 개체를 구성 했으므로 적어도 한 번의 복사 / 이동은 불가피합니다. 이 경우 emplace_back()over 를 사용하면 이점이 없습니다 push_back().

Otherwise, I agree with everyone else saying that it's not a premature optimization because the move semantics models what you are trying to do more closely than making a copy of the object.


Yes, it is premature optimization if it is premature optimization.

Let me elaborate:
Premature optimization is defined by whether you are optimizing a part of the code that you don't know to be performance critical. That is, premature optimization is never defined by the method of optimization, it is always defined by the place of optimization and your knowledge about what you are doing.


Now, to the advisability to optimize using std::move():

With std::move() you avoid the heavy lifting of copy construction, like memory allocation, deallocation, copy constructing contained elements, deconstructing contained elements, etc. That is good. But one part remeains: the construction/destruction of the container object.

emplace_back() has the virtue of entirely avoiding the construction of the temporary object. So, whenever you can avoid a temporary object by using emplace_back(), you have a small win.

Considering code quality (read readability/maintainability): std::move() has the downside of leaving you with an unusable object, which can be a source of bugs. This does not happen with emplace_back(). So, again, the later is clearly preferable.

Of course, emplace_back() cannot be used in all contexts that allow the use of std::move(). So, if these are performance critical, std::move() may be the way to go. There are some very valid use-cases for optimization with std::move(). However, you might also find out that you can write the code in a way that does not require any copy/move/emplace construction at all. Never stop looking for a better solution when optimizing!

In the end, it remains that the validity of optimizing with std::move() depends entirely on the context: It is good optimization wherever it is good optimization.

참고URL : https://stackoverflow.com/questions/25529582/is-it-a-premature-optimization-to-use-stdmove

반응형