std:move에서 데이터를 이동하지 않는 문제[C++ 트랩#1]

10491 단어 C++movetech

개시하다


대상


다음은 해당자를 대상으로 한 보도.
  • C++의 입문 완료
  • std::move 불필요한 복사본을 피하기 위해 대충 사용
  • C 스타일로 정렬
  • 지침의 사용 방법이 정확한지 걱정
  • 언제 쓸모없는 복사본이 생길지 모른다
  • 주의점

  • class/구조체struct의 뜻은 다르지 않다.같은 물건을 만들어 보세요.
  • 본문에는 필자의 주관적인 감상이 다소 포함되어 있다.꼭 사실일 필요는 없고, 확인이 부족한 부분은 주석으로 통지한다.
  • 필자는 글을 쓰는 데 익숙하지 않아서 잘 보이지 않는다.미안합니다.
  • std:move 뜻의 오해


    C++를 시작할 때'std:move 자체가 데이터를 이동하지 않는다'는 말을 자주 듣는다.
    입문할 때 "그랬구나"라고만 생각하지만 곰곰이 생각해보면 불안하다.
    어느 정도 카테고리를 사용하면 std::move를 사용하여 복사를 피한다.
    다만, std::move 사용장소를 잘 이해하지 못하면 C++에서 불필요한 복사본이 대거 발생할 수 있다.
    move라는 단어의 의미로 잘못 알기 쉬운 방법std::move 때문에 입문 후 학급/구조체를 어느 정도 사용한 C++ 초급자~중급자 정도에 대한 해설을 다시 하려고 합니다.

    잘못된 std:move 사용 방법


    만약 이런 코드를 썼다면 쓸모없는 복사본이 생겼을 가능성이 높다.
    예를 들어 대량의 표량형 구성원이 존재하는 거대한 구조Huge를 가정한다.[1] [2]
    struct Huge {
      char name[256];
      int age;
    };
    
    이때 다음은 쓸모없는 복사가 발생하는 코드입니다.
    ex1.cpp
    Huge a;
    Huge b = std::move(a);
    
    ex2.cpp
    struct Foo {
      Huge mHuge;
      Foo(Huge&& huge)
        : mHuge(std::move(huge))
      {}
    };
    
    Huge a;
    Foo b { std::move(a) };
    
    ex3.cpp
    Huge a;
    Huge b;
    std::swap(a, b);
    
    ex3.cpp 사용std::swap, std::swap 내부 사용std::move.[3] ex2.cpp는 직관적인 코드로 필자는 실제로 코드std::move를 썼지만 그 뜻을 잘 조사하지 못했다.
    실제로 ex2.cpp 의 작법은 Huge 모두 복제되었다.[1:1]

  • 정확한 학급 제작 방법
  • 정확한 의미std::move
  • 이 둘을 잘 이해하지 못하면 아무리std::move쓸데없는 복사본을 피해도 무의미해진다.
    C++는'속도가 빠르다','효율이 높다'고 불리지만 속도와 효율을 높이기 위해서는 작은 오류도 주의해야 한다.
    C++ 불완전한 사용은 다른 고급 언어에 비해 위험할 수 있습니다.
    'std::move를 사용해도 복사가 발생한다'는 점에 대해서는 아래에 자세히 설명한다.

    std:move 사용 방법


    구조체의 예


    다음과 같은 거대한 구조Huge와 그 실례a가 있다고 가정한다.[1:2]
    struct Huge {
      char name[256];
      int age;
    };
    
    인스턴스ab로 이동하려면 다음과 같이 하십시오.
    Huge a;
    Huge b = std::move(a);
    

    이렇게 하면 a 복제된 b 의 성능과 같다.[1:3]
    이것은 쓸모없는 복제품이어서 원하지 않는 행위가 있을 수 있다.

    C 언어 시대의 대책


    따라서 C 언어의 코드는 구조체를 처리할 때 지침을 사용한다.
    Huge *a = malloc(sizeof(Huge));
    
    free(a);
    
    포인터를 사용하면 다른 변수에 전송되더라도 주체의 복제가 일어나지 않고 포인터만 복제하면 되기 때문에 데이터의 복제는 최소한으로 수납할 수 있다.
    Huge *b = a;
    
    그러나 unique_ptr 등 스마트 포인터가 없는 C 언어에서는 원시 포인터만 직접 사용할 수 있기 때문에 다중해방과 메모리 유출에 자주 직면해야 한다.
    free(b);
    free(a); // 多重解放
    

    스마트 포인터 사용


    방금 C 언어의 코드를 C++의 스마트 포인터로 교체합니다.
    std::unique_ptr<Huge> a = std::make_unique<Huge>();
    std::unique_ptr<Huge> b = std::move(a);
    
    를 사용하여 소유권을 a에서 b로 이전한다.
    여기서 가장 중요한 것은 이런 상황std::move은'이동 소유권'일 뿐'이동 데이터'가 아니다.
    스마트 포인터를 사용하면 불필요한 복제를 피할 수 있고 대상을 효과적으로 관리할 수 있다.

    해결 방법 1 포인터 사용(스마트 포인터)


    요약하면 포인터(스마트 포인터)를 사용하여 구조체/클래스의 무용지물 복제를 피하는 해결 방법이 있다는 것을 알 수 있습니다.
    그러나 C++를 사용하면 학급 사용자의 고려 외에 학급 제공자 측의 고려도 중요하다.
    스마트 포인터를 사용해도 되지만 1급 수준을 한층 높이기 위해 이 반 제공자 측의 고려를 고려해 보자.(해결 방법 2)

    해결 방법 2 "반에서 고민"


    학급 제공자 측의 고려는'올바른 학급의 행태·응당한 모습'으로 설명하려 했으나 주제를 조금 벗어나 다른 기사로 쓰기로 했다.(완료되면 링크 붙여넣기)

    총결산


    종합하면'std::move = 데이터의 이동'은 사실상 잘못된 해석이다.
    먼저 입문서상 흔히 있는 것처럼 "std::move 자체는 데이터를 이동하지 않는다"고 설명했다.
    이걸 "std::move=데이터의 이동"으로 해석하자면 사용한 C++ 프로그래머는 과거 필자처럼 다소...
    std::move의 의미 문제는 특히 간과하기 쉬운 함정이다
    이외에도 C++에는 많은 트랩이 숨겨져 있습니다.
    이런 위험한 언어를 얼렁뚱땅 사용하는 것이 오류와 오류를 초래하는 원인이다.
    어떤 프로그래머든지 실수를 해서 실수를 할 수 있다.
    다만, 무용한 복제 문제는 오류는 물론 경고와 설명도 없는 번거로운 오류로 성능이 현저히 떨어지는 원인 중 하나다.
    필자는 C++보다 현대적이고 안전한 언어를 사용하는 것이 개발 효율과 집행 효율을 높일 수 있다고 생각한다.
    향후 개발에 참고가 될 수 있다면 좋겠네요.
    감사합니다.
    각주
    구성원이 수조나 간단한 경우 처리 시스템에 따라 복사와 동등한지 비복사인지 구분할 수 있으므로 모든 구성원이 복제될 수 있는 클래스로 생각하십시오.↩︎ ↩︎ ↩︎ ↩︎
    보통 이런 구조체를 피해야 한다.char[256]→std:string처럼 효율적으로 써야 한다.그리고 std:string은 복사하지 않습니다.그러나 표량형 구성원이 많은 반에서는 대량의 복사본이 발생한다.↩︎
    C++ 표준의 함수, 클래스 등은 내용이 언어 표준을 통해 확정되지 않았기 때문에 반드시 사용하지 않는다std::move.(컴파일러만의 함수를 사용할 수 있음) ↩︎

    좋은 웹페이지 즐겨찾기