2016-10-31 1 views
5

Qt5와 QMAKE_CXXFLAGS += -std=c++1y을 사용하여 새 프로젝트를 시작합니다. 나는 QScopedPointer 또는 std::unique_ptr을 선호해야하는지 잘 모르겠습니다.QScopedPointer 또는 std :: unique_ptr을 사용해야합니까?

somewhere 나는 QScopedPointer이 더 이상 이상하지 않습니다.

QScopedPointer에는 어떤 기능이 있습니까? unique_ptr이 부족합니까? unique_ptr의 기능이 있습니까? QScopedPointer을 대체 할 때 원하지 않는 기능이 있습니까? 혹은 그 반대로도?

+3

나는'std :: unique_ptr'을 사용할 것입니다. – NathanOliver

+0

Qt 스마트 포인터의 사용량을 줄이고'std :: shared_ptr'과'std :: unique_ptr'을 사용하는 것으로 옮겼습니다. – drescherjm

+2

표준 라이브러리와 다른 라이브러리 중 하나를 선택할 때마다 필자는 이유가없는 한 항상 표준 라이브러리를 선택합니다. 하나의 설득력있는 이유는 다른 유형을 사용하는 코드와의 상호 운용성이 필요한 경우입니다. –

답변

5

QScopedPointer은 이동 의미 체계를 지원하지 않으므로 정확히 unique_ptr보다 약합니다.

그 기능은 다른 점에서는 매우 유사합니다.

이동 의미는 매우 유용하며 실수로 잘못 사용하면 문제가 발생하는 경우는 거의 없습니다. 따라서 그들은 무해한 것에서부터 (더 일반적으로) 도움이되는 것까지 매우 그렇습니다.

QScopedPointer을 사용해야하는 유일한 이유는 기존 코드 기반과의 상호 운용성입니다. 그리고 거기에서도, 그들이 얼마나 유사한 지 알면, 어댑터는 꽤 쉬울 것입니다.

적응할 필요가없는 경우 unique_ptr을 사용하십시오.


이제는 적응에 대해 논의 할 것입니다.

까다로운 부분은 QScopedPointer의 두 번째 매개 변수입니다. 매우 대략적으로 두 번째 매개 변수 unique_ptr에 해당합니다.

unique_ptr에는 상태 저장자가 허용됩니다. QScopedPointer에서는 그렇지 않습니다.

static void cleanup(T* pointer) 

꽤 일대일의 unique_ptr에서

void operator()(T* pointer)const 

에 해당합니다.따라서 :

template<class QDelete> 
struct std_deleter { 
    template<class T> 
    void operator()(T* target) const { 
    QDelete::cleanup(target); 
    } 
}; 

은 Qt deleter를 std deleter에 매핑합니다. 다른 방법은 비 저장되는 Deleter가에 의해 제한됩니다

template<class Std_deleter> 
struct Qt_deleter { 
    template<class T> 
    static void cleanup(T* target) { 
    static_assert(std::is_empty<Std_deleter>{}, "Only works with stateless deleters"); 
    Std_deleter{}(target); 
    } 
}; 

우리가 지금 변환 할 수 있습니다

당신이 QScopedPointer를 사용하는 거라고 유일한 이유에 대해 설명합니다
template<class T, class D> 
QScopedPointer<T, Qt_deleter<D>> 
to_qt(std::unique_ptr<T, D>&& src) { 
    return src.release(); 
} 
template<class T, class D> 
QScopedPointer<T, Qt_deleter<D>> 
to_qt(std::unique_ptr<T[], D>&& src) { 
    return src.release(); 
} 
template<class T> 
QScopedPointer<T> 
to_qt(std::unique_ptr<T>&& src) { 
    return src.release(); 
} 
template<class T> 
QScopedPointer<T, QScopedPointerArrayDeleter> 
to_qt(std::unique_ptr<T[]>&& src) { 
    return src.release(); 
} 
template< 
    class T, class D, class R=std::unique_ptr<T, std_deleter<D> > 
> 
to_std(QScopedPointer<T, D>&& src) { 
    return R(src.take()); // must be explicit 
} 
template<class T, class R=std::unique_ptr<T>> 
to_std(QScopedPointer<T>&& src) { 
    return R(src.take()); // must be explicit 
} 
template<class T, class R=std::unique_ptr<T[]>> 
to_std(QScopedPointer<T,QScopedPointerArrayDeleter >&& src) { 
    return R(src.take()); // must be explicit 
} 

. 몇 가지 경우가 있습니다. 기본 삭제 자 QScopedPointer은 기본값 인 std::unique_ptr으로 변환해야하며 반대의 경우도 마찬가지입니다.

어레이 삭제 QScopedPointerunique_ptr<T[]>으로, 그 반대로 변환되어야합니다.

다른 경우에는 단순히 Deleter를 마무리합니다. 이론 상으로는 정말 멋진 트릭은 들어오는 Deleter가 이미 포장되어 있고 포장을 뒤집어 썼는지를 알아 차리는 것이지만, 만약 당신의 코드가 많은 왕복을하고 있다면 아마도 이미 잘못된 것일 것입니다.

+3

"기존 코드 기반과의 상호 운용성"나는 "상호 운용성"이라고 부르지 않을 것입니다. 'QScopedPointer'는 C++ 98 코드베이스를위한 것이기 때문에 (QScopedPointer는 이동 의미론을 가지고 있지 않습니다). 사용자가 이동할 수 없다는 점을 감안할 때, 일반적으로 구현 보조 장치 일 뿐이며 API에서는 공개되지 않습니다 (unique_ptr과 달리). 그리고 Qt 프로젝트는 의도적으로'QScopedPointer'를 조금이라도 더 잘 만들지 않습니다 - 당신은 이미 그것을 가지고 있습니다, 그것은'unique_ptr'입니다. 새로운 C++ 11 지원 프로젝트에서는'QScopedPointer'가 아닌'unique_ptr'을 사용하십시오. – peppe

+0

@peppe 참조를 통해 QScopedPointer를 "반환"하고 QScopedPointer ref 및 cref를 통해 매개 변수를 취하는 1000 만 줄의 코드베이스를 상상해보십시오. 더 이상 소스가 없지만 기능을 보존해야하는 기존 라이브러리 중 일부는 temble입니다. 요점은 기존 코드베이스의 파괴 된 hellscape를 가지고 있더라도 QScopedPointer를 사용하지 않는 것입니다. 'to_qt'와'to_std'를 사용하십시오. – Yakk

0

두 클래스의 주된 의도는 비슷하지만 비즈니스 결정을 내리는 두 가지 중요한 차이점이 있습니다.

QScopedPointer에는 할당 연산자가 없습니다. 여기서 std :: unique_ptr에는 대입 연산자가 있습니다.

QT 개체/컨트롤을 엄격하게 사용하고 할당을 원하지 않는 경우 QScopedPointer를 사용하십시오.

+2

'const unique_ptr'에도 할당 연산자가 없습니다. –

+1

예. 그러나 OP는 const를 말하지 않았다. – Naidu

1

왜 표준 라이브러리의 내용이 아닌 표준 라이브러리의 내용을 사용합니까?

내게는 좋은 프로그래머가 그렇게하는 유일한 이유가 있습니다. 외부 라이브러리가 표준 라이브러리에서 제공하지 않는 것을 제공한다면. 그럴까요?

향후 프로그램의 이식성 및 업데이트를 고려한 다음 결정하십시오.

관련 문제