공식 Qt 예제와 튜토리얼에서 스마트 포인터를 사용하지 않는 이유는 무엇입니까?
Qt 라이브러리에 대한 공식 예제와 튜토리얼이 스마트 포인터를 사용하지 않는 이유는 무엇입니까? 난 단지 참조 new
및 delete
위젯을 생성하고 파괴.
나는 근거를 찾았지만 그것을 찾을 수 없었고, 역사적인 이유나 이전 버전과의 호환성을 제외하고는 직접 볼 수 없습니다. 모든 사람이 위젯 생성자가 실패 할 경우 프로그램이 종료되기를 원하지는 않으며 try / catch를 통해 처리합니다. 블록은보기 흉합니다 (몇 군데에서 사용 되더라도). 부모 위젯이 자식의 소유권을 가질 수 있다는 사실은 delete
일부 수준에서 부모를 위해 여전히 사용해야 하므로 부분적으로 만 설명합니다 .
Qt는 Qobject 리소스를 관리하기 위해 부모-자식 모델에 의존하기 때문입니다. 이벤트 관리에서 메모리 관리, 그리기, 파일 처리 등에 사용되는 복합 + 책임 체인 패턴을 따릅니다.
실제로 공유 \ 고유 포인터에서 QObject를 사용하려는 시도 는 과도하게 엔지니어링됩니다 (99 %의 시간).
- deleteLater를 호출 할 사용자 지정 삭제자를 제공해야합니다.
- 부모가있는 qobject에는 이미 부모 개체에 참조가 있습니다. 따라서 부모가 존재하는 한 객체가 누출되지 않는다는 것을 알고 있습니다. 제거해야 할 때
deleteLater
직접 전화 할 수 있습니다. - 부모가없는 QWidget은 이미 Qapplication 객체에 참조가 있습니다. 포인트 2와 동일합니다.
즉, Qt와 함께 RAII를 계속 사용할 수 있습니다. 예를 들어 QPointer 는 QObject
. 내가 사용하는 것 QPointer<QWidget>
보다는 QWidget*
.
참고 : 너무 fanboy, 두 단어 : Qt + valgrind.
어린이를위한 스마트 포인터
스마트 포인터 클래스 std::unique_ptr
및 std::shared_ptr
메모리 관리를위한 것입니다. 이러한 스마트 포인터가 있다는 것은 포인터 를 소유 하고 있음을 의미 합니다. 그러나 부모 QObject
와 함께 또는 파생 유형을 만들 때 QObject
소유권 (정리 책임)이 부모에게 넘겨 QObject
집니다. 이 경우 표준 라이브러리 스마트 포인터는 잠재적으로 이중 삭제를 유발할 수 있으므로 불필요하거나 위험합니다. 이런!
고아에 대한 원시 포인터
그러나 QObject
부모없이 힙에 (또는 파생 된 형식)이 만들어지면 QObject
상황이 매우 다릅니다. 이 경우 원시 포인터가 아니라 스마트 포인터, 가급적 std::unique_ptr
객체에 대한 a 를 유지해야합니다. 그렇게하면 자원 안전을 얻을 수 있습니다. 나중에 객체 소유권을 부모 QObject
에게 넘기는 경우 다음 std::unique_ptr<T>::release()
과 같이 사용할 수 있습니다 .
auto obj = std::make_unique<MyObject>();
// ... do some stuff that might throw ...
QObject parentObject;
obj->setParent( &parentObject );
obj.release();
고아에게 부모를 제공하기 전에 수행 한 작업에서 예외가 발생하면 원시 포인터를 사용하여 객체를 보유하면 메모리 누수가 발생합니다. 그러나 위의 코드는 그러한 누출을 방지합니다.
보다 일반적인 참고 사항
원시 포인터를 모두 함께 피하는 것은 최신 C ++ 조언이 아니라 원시 포인터 소유 를 피하는 것 입니다. 또 다른 최신 C ++ 조언을 추가 할 수 있습니다 . 다른 프로그램 엔티티가 소유 한 객체에 스마트 포인터를 사용하지 마십시오.
이미 질문에 답하셨습니다 except if it's for historic reasons/backward compatibility
.. QT만큼 큰 라이브러리는 라이브러리를 사용하는 모든 사람이 C ++ 11을 지원하는 컴파일러를 가지고 있다고 가정 할 수 없습니다. new
및 delete
이전 기준에 존재하는 보장됩니다.
그러나 스마트 포인터 사용에 대한 지원이 있다면 원시 포인터보다 사용하는 것이 좋습니다.
@Jamey가 말한 것 외에도 :
영리하게 디자인하면 위젯에서 삭제를 사용할 필요가 없습니다. 메인 윈도우가 있고 그것의 자동 객체를 생성하고 이벤트 루프에서 해당 윈도우를 실행한다고 가정 해 보겠습니다. 이제 나머지는이 위젯의 모든 항목을 자식으로 추가 할 수 있습니다. 그리고이 MainWindow에 자식으로 직접 / 간접적으로 추가하기 때문에이 메인 창을 닫을 때 모든 것이 자동으로 처리됩니다. 생성 한 모든 동적 개체 / 위젯이 MainWindow의 자식 / 손자인지 확인하기 만하면됩니다. 따라서 명시적인 삭제가 필요하지 않습니다.
QObject
부모가 정의되고 프로그램의 구조와 같은 트리는 메모리를 매우 효과적으로 관리 할 수 있습니다.Qt의 역동 성은 예를 들어 원시 포인터를 주변에 전달하는 것과 같은 멋진 이상을 깨뜨립니다. 쉽게을 붙잡을 수
dangling pointer
있지만 프로그래밍에서 일반적인 문제입니다.실제로 약한 참조 인 Qt 스마트 포인터
QPointer<T>
는 STL 캔디의 일부를 제공합니다.하나는
std::unique_ptr
등과 혼합 할 수도 있지만 프로그램에서 비 Qt 기계에만 사용해야합니다.
'developer tip' 카테고리의 다른 글
Pandas to_html ()은 문자열 내용을 자릅니다. (0) | 2020.11.08 |
---|---|
MongoDB 데이터 디렉토리 / data / db를 찾을 수 없습니다. (0) | 2020.11.08 |
최상의 이미지 축소 알고리즘 (품질 측면)은 무엇입니까? (0) | 2020.11.08 |
새 C ++ 프로젝트에 ATL, MFC, Win32 또는 CLR을 사용할지 어떻게 결정합니까? (0) | 2020.11.08 |
페이지 언로드시 JQuery를 사용한 Ajax 요청 (0) | 2020.11.08 |