std:move에서 데이터를 이동하지 않는 문제[C++ 트랩#1]
개시하다
대상
다음은 해당자를 대상으로 한 보도.
std::move
불필요한 복사본을 피하기 위해 대충 사용주의점
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.cppstruct Foo {
Huge mHuge;
Foo(Huge&& huge)
: mHuge(std::move(huge))
{}
};
Huge a;
Foo b { std::move(a) };
ex3.cppHuge 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;
};
인스턴스a
를 b
로 이동하려면 다음과 같이 하십시오.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
.(컴파일러만의 함수를 사용할 수 있음) ↩︎Reference
이 문제에 관하여(std:move에서 데이터를 이동하지 않는 문제[C++ 트랩#1]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/fugi/articles/6a280eb5a29b04텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)