IT TIP

표준 라이브러리는 std :: swap을 어떻게 구현합니까?

itqueen 2020. 12. 25. 10:42
반응형

표준 라이브러리는 std :: swap을 어떻게 구현합니까?


STL에서 스왑 기능은 어떻게 구현됩니까? 다음과 같이 간단합니까?

template<typename T> void swap(T& t1, T& t2) {
    T tmp(t1);
    t1=t2;
    t2=tmp;
}

다른 게시물에서는이 기능을 자신의 수업에 특화시키는 것에 대해 이야기합니다. 왜 이렇게해야합니까? std::swap기능을 사용할 수없는 이유는 무엇 입니까?


어떻게 std::swap구현됩니까?

예, 질문에 제시된 구현은 클래식 C ++ 03입니다.

보다 현대적인 (C ++ 11) 구현은 std::swap다음과 같습니다.

template<typename T> void swap(T& t1, T& t2) {
    T temp = std::move(t1); // or T temp(std::move(t1));
    t1 = std::move(t2);
    t2 = std::move(temp);
}

이는 불필요한 복사본 등을 방지하기 때문에 리소스 관리 측면에서 기존 C ++ 03 구현에 비해 개선 된 것입니다. C ++ 11 std::swap에서는 유형 TMoveConstructibleMoveAssignable이어야 하므로 구현 및 개선이 가능합니다. .

맞춤형 구현을 제공해야하는 이유는 무엇입니까?

swap특정 유형에 대한 의 사용자 정의 구현 은 일반적으로 구현이 표준 버전보다 더 효율적이거나 구체적 일 때 권장됩니다.

이에 대한 전형적인 예는 복사 및 삭제 비용이 많이 드는 많은 양의 리소스를 클래스에서 관리하는 경우입니다. 대신 사용자 지정 구현은 스왑에 영향을주는 데 필요한 핸들이나 포인터를 간단히 교환 할 수 있습니다.

std::moveC ++ 11 이후부터 이동 가능한 유형 (그리고 유형을 구현) 의 출현으로 여기에있는 많은 원래의 근거가 사라지기 시작했습니다. 그럼에도 불구하고 사용자 정의 스왑이 표준 스왑보다 낫다면 구현하십시오.

일반 코드는 ADL 메커니즘을 적절하게 swap사용하는 경우 일반적으로 사용자 정의를 사용할 수 있습니다 .


STL에서 스왑 기능은 어떻게 구현됩니까?

어떤 구현? 이것은 하나의 구체적인 라이브러리가 아니라 사양입니다. 내 컴파일러의 표준 라이브러리가 어떻게 작동하는지 의미한다면 어떤 컴파일러인지 알려주거나 코드를 직접 읽으십시오.

다음과 같이 간단합니까?

그것은 본질적으로 C ++ 11 이전의 순진한 버전입니다.

이 특수화되지 않은 구현은 복사를 강제 T = std::vector<SomethingExpensive>합니다. 예를 들어 코드는 다음과 같이 번역됩니다.

template<typename T> void swap(T& t1, T& t2) {
  T tmp(t1); // duplicate t1, making an expensive copy of each element
  t1=t2;     // discard the original contents of t1,
             // and replace them with an expensive duplicate of t2
  t2=tmp;    // discard the original contents of t2,
             // and replace them with an expensive duplicate of tmp
}            // implicitly destroy the expensive temporary copy of t1

그래서 두 벡터를 교환하기 위해 우리는 본질적으로 세 개의 . 3 개의 동적 할당과 많은 비용이 많이 드는 개체가 복사되었으며 이러한 작업 중 하나가 발생하여 인수가 불확실한 상태로 남을 수 있습니다.

이것은 명백히 끔찍했기 때문에 값 비싼 컨테이너에 과부하가 제공되었고 자신의 값 비싼 유형에 대한 과부하를 작성하도록 권장되었습니다. std::vector전문화는 벡터의 내부에 접근했다, 모든 복사하지 않고 두 벡터를 교환 할 수 있습니다 :

template <typename T> void swap(vector<T> &v1, vector<T> &v2) { v1.swap(v2); }
template <typename T> void vector<T>::swap(vector<T>& other) {
  swap(this->size_, other.size_); // cheap integer swap of allocated count
  swap(this->used_, other.used_); // cheap integer swap of used count
  swap(this->data__, other.data_); // cheap pointer swap of data ptr
}

여기에는 비용이 많이 들고 동적 (해제) 할당이없는 복사본이 포함되지 않으며 던지지 않는 것이 보장됩니다.

이제이 전문화의 이유는 vector :: swap이 vector의 내부에 액세스 할 수 있고 복사하지 않고도 안전하고 효율적으로 이동할 수 있기 때문입니다.

왜 내가 [자신의 수업을 위해 전문화]를해야합니까?

Pre-C ++ 11 std::vector은 스와핑을 효율적이고 예외적으로 안전하게 만들기 위해 다음과 같은 이유 입니다.

C ++ 11 이후로 이동 구성 및 할당을 제공하거나 컴파일러가 정상적인 기본값을 생성 할 수있는 경우에는 그렇지 않습니다.

새로운 일반 스왑 :

template <typename T> void swap(T& t1, T& t2) {
    T temp = std::move(t1);
    t1 = std::move(t2);
    t2 = std::move(temp);
}

이동 생성 / 할당을 사용하여 사용자 정의 구현을 전혀 작성할 필요없이 위의 사용자 정의 벡터 구현과 본질적으로 동일한 동작을 얻을 수 있습니다.

참조 URL : https://stackoverflow.com/questions/25286544/how-does-the-standard-library-implement-stdswap

반응형