QSharedDataPointer Class

template <typename T> class QSharedDataPointer

QSharedDataPointer 클래스는 암시적으로 공유되는 객체에 대한 포인터를 나타냅니다. 더 보기...

Header: #include <QSharedDataPointer>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core

참고: 이 클래스의 모든 함수는 재인용됩니다.

공용 유형

공용 함수

QSharedDataPointer()
QSharedDataPointer(T *data)
(since 6.0) QSharedDataPointer(T *data, QAdoptSharedDataTag)
QSharedDataPointer(const QSharedDataPointer<T> &o)
QSharedDataPointer(QSharedDataPointer<T> &&o)
~QSharedDataPointer()
const T *constData() const
T *data()
const T *data() const
void detach()
(since 6.0) T *get()
(since 6.0) const T *get() const
(since 6.0) void reset(T *ptr = nullptr)
void swap(QSharedDataPointer<T> &other)
(since 6.0) T *take()
T *operator T *()
const T *operator const T *() const
bool operator!() const
T &operator*()
const T &operator*() const
T *operator->()
const T *operator->() const
QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other)
QSharedDataPointer<T> &operator=(T *o)
QSharedDataPointer<T> &operator=(const QSharedDataPointer<T> &o)

보호된 함수

T *clone()
bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
bool operator!=(const T *ptr, const QSharedDataPointer<T> &rhs)
bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)
bool operator==(const T *ptr, const QSharedDataPointer<T> &rhs)

상세 설명

QSharedDataPointer<T>는 암시적으로 공유되는 자신만의 클래스를 쉽게 작성할 수 있게 해줍니다. QSharedDataPointer는 스레드 안전 참조 카운팅을 구현하여 재진입 클래스에 QSharedDataPointers를 추가해도 재진입이 되지 않도록 보장합니다.

암시적 공유는 포인터의 속도와 메모리 효율을 클래스의 사용 편의성과 결합하기 위해 많은 Qt 클래스에서 사용됩니다. 자세한 내용은 공유 클래스 페이지를 참조하십시오.

Employee 클래스를 암시적 공유로 만들고 싶다고 가정해 봅시다. 절차는 다음과 같습니다:

  • QSharedDataPointer<EmployeeData> 유형의 단일 데이터 멤버를 갖도록 Employee 클래스를 정의합니다.
  • QSharedData 에서 파생된 EmployeeData 클래스가 일반적으로 Employee 클래스에 넣었을 모든 데이터 멤버를 포함하도록 정의합니다.

이를 실제로 보여주기 위해 암시적으로 공유되는 Employee 클래스의 소스 코드를 검토해 보겠습니다. 헤더 파일에서 EmployeeEmployeeData 두 클래스를 정의합니다.

#include <QSharedData>
#include <QString>

class EmployeeData : public QSharedData
{
  public:
    EmployeeData() : id(-1) { }
    EmployeeData(const EmployeeData &other)
        : QSharedData(other), id(other.id), name(other.name) { }
    ~EmployeeData() { }

    int id;
    QString name;
};

class Employee
{
  public:
    Employee() { d = new EmployeeData; }
    Employee(int id, const QString &name) {
        d = new EmployeeData;
        setId(id);
        setName(name);
    }
    Employee(const Employee &other)
          : d (other.d)
    {
    }
    void setId(int id) { d->id = id; }
    void setName(const QString &name) { d->name = name; }

    int id() const { return d->id; }
    QString name() const { return d->name; }

  private:
    QSharedDataPointer<EmployeeData> d;
};

Employee 클래스에서 단일 데이터 멤버인 QSharedDataPointer<EmployeeData> 유형의 d 포인터에 주목하세요. 직원 데이터에 대한 모든 액세스는 d 포인터의 operator->() 을 거쳐야 합니다. 쓰기 액세스의 경우 operator->() 는 공유 데이터 객체의 참조 수가 1보다 큰 경우 공유 데이터 객체의 복사본을 만드는 detach()를 자동으로 호출합니다. 이렇게 하면 하나의 Employee 객체에 대한 쓰기가 동일한 EmployeeData 객체를 공유하는 다른 Employee 객체에 영향을 미치지 않습니다.

EmployeeData 클래스는 백그라운드 참조 카운터를 제공하는 QSharedData 을 상속합니다. EmployeeData 에는 기본 생성자, 복사 생성자, 소멸자가 있습니다. 일반적으로 암시적으로 공유되는 클래스의 데이터 클래스에는 이러한 사소한 구현이 전부입니다.

Employee 클래스에 대한 두 개의 생성자를 구현하는 것도 간단합니다. 둘 다 EmployeeData 의 새 인스턴스를 생성하고 이를 d 포인터에 할당합니다.

    Employee() { d = new EmployeeData; }

    Employee(int id, const QString &name) {
        d = new EmployeeData;
        setId(id);
        setName(name);
    }

Employee 클래스에도 사소한 복사 생성자가 정의되어 있지만 이 경우 반드시 필요한 것은 아닙니다.

    Employee(const Employee &other)
          : d (other.d)
    {
    }

EmployeeData 클래스는 Employee (employee.h) 클래스와 같은 파일에 포함되어 있으므로 여기에서는 복사 생성자가 반드시 필요한 것은 아닙니다. 그러나 QSharedData 의 비공개 하위 클래스를 QSharedDataPointer를 포함하는 공개 클래스와 같은 파일에 포함하는 것은 일반적이지 않습니다. 일반적으로 QSharedData 의 비공개 하위 클래스는 공개 파일에 포함되지 않는 별도의 파일에 넣어 사용자에게 숨기는 것이 좋습니다. 이 경우 일반적으로 EmployeeData 클래스를 employee.h 에 포함되지 않는 별도의 파일에 넣습니다. 대신 employee.hEmployeeData 비공개 서브클래스를 미리 선언합니다:

    class EmployeeData;

여기서 이렇게 했다면 표시된 복사 생성자가 필요했을 것입니다. 복사 생성자는 사소한 것이므로 항상 포함하는 것이 좋습니다.

그 이면에는 Employee 객체가 복사, 할당 또는 매개변수로 전달될 때마다 QSharedDataPointer가 참조 수를 자동으로 증가시킵니다. Employee 개체가 삭제되거나 범위를 벗어날 때마다 참조 카운트가 감소합니다. 공유된 EmployeeData 객체는 참조 카운트가 0에 도달하면 자동으로 삭제됩니다.

Employee 의 생성자가 아닌 멤버 함수에서 d 포인터가 역참조될 때마다 QSharedDataPointer는 자동으로 detach()를 호출하여 함수가 자체 데이터 복사본에서 작동하도록 합니다.

    void setId(int id) { d->id = id; }

    void setName(const QString &name) { d->name = name; }

d 포인터의 여러 역참조로 인해 멤버 함수에서 detach()가 두 번 이상 호출되는 경우, detach()는 처음 호출될 때만 공유 데이터의 복사본을 생성하며, 이후 detach() 호출 시 참조 횟수가 다시 1이 되므로 주의하세요.

그러나 직원 ID와 이름을 받는 두 번째 Employee 생성자에서는 setId()와 setName()이 모두 호출되지만 새로 생성된 EmployeeData 객체의 참조 카운트가 방금 1로 설정되었으므로 쓰기 시 복사본이 생성되지 않습니다.

Employeeconst 멤버 함수에서 d 포인터를 역참조해도 detach()가 호출되지 않습니다.

    int id() const { return d->id; }

    QString name() const { return d->name; }

C++ 컴파일러에서 제공하는 복사 생성자와 할당 연산자가 필요한 멤버별 얕은 복사를 수행하므로 Employee 클래스에 대해 복사 생성자나 할당 연산자를 구현할 필요가 없다는 점에 유의하세요. 복사할 유일한 멤버는 d 포인터로, QSharedDataPointer이며, operator=() 는 공유 EmployeeData 객체의 참조 수를 증가시킬 뿐입니다.

암시적 공유와 명시적 공유

암시적 공유는 Employee 클래스에 적합하지 않을 수 있습니다. 암시적으로 공유되는 Employee 클래스의 인스턴스 두 개를 생성하는 간단한 예제를 살펴봅시다.

#include "employee.h"

int main()
{
    Employee e1(1001, "Albrecht Durer");
    Employee e2 = e1;
    e1.setName("Hans Holbein");
}

두 번째 직원 e2가 생성되고 e1이 할당된 후 e1e2 모두 직원 1001인 알브레히트 듀러를 참조합니다. Employee 객체는 모두 참조 카운트가 2인 EmployeeData 의 동일한 인스턴스를 가리킵니다. 그런 다음 e1.setName("Hans Holbein") 을 호출하여 직원 이름을 변경하지만 참조 카운트가 1보다 크므로 이름이 변경되기 전에 쓰기 시 복사본이 수행됩니다. 이제 e1e2 는 서로 다른 EmployeeData 개체를 가리킵니다. 이름은 다르지만 둘 다 ID가 1001이므로 원하지 않을 수도 있습니다. 물론 두 번째 고유한 직원을 만들려는 경우에는 e1.setId(1002) 을 계속 사용할 수 있지만 모든 곳에서 직원의 이름만 변경하려는 경우에는 암시적 공유 대신 Employee 클래스에서 explicit sharing 을 사용하는 것이 좋습니다.

Employee 클래스에서 d 포인터를 QExplicitlySharedDataPointer<EmployeeData> 으로 선언하면 명시적 공유가 사용되며 복사 시 쓰기 작업이 자동으로 수행되지 않습니다(즉, detach()는 컨스트가 아닌 함수에서 호출되지 않음). 이 경우 e1.setName("Hans Holbein") 이후 직원의 이름은 변경되었지만 e1과 e2 모두 여전히 EmployeeData 의 동일한 인스턴스를 참조하므로 ID 1001 을 가진 직원은 한 명뿐입니다.

멤버 함수 문서에서 d 포인터는 항상 공유 데이터 객체에 대한 내부 포인터를 가리킵니다.

Qt 컨테이너에서 사용하기 위한 성능 최적화

암시적으로 공유되는 클래스가 위의 Employee 클래스와 유사하고 QSharedDataPointer 또는 QExplicitlySharedDataPointer 를 유일한 멤버로 사용하는 경우 Q_DECLARE_TYPEINFO() 매크로를 사용하여 이동 가능한 유형으로 표시하는 것을 고려해야 합니다. 이렇게 하면 Qt의 컨테이너 클래스를 사용할 때 성능과 메모리 효율성을 향상시킬 수 있습니다.

QSharedData, QExplicitlySharedDataPointer, QScopedPointer, QSharedPointer참조하십시오 .

멤버 유형 문서

QSharedDataPointer::Type

공유 데이터 객체의 유형입니다. d 포인터는 이 유형의 객체를 가리킵니다.

멤버 함수 문서

[noexcept] QSharedDataPointer::QSharedDataPointer()

nullptrd 포인터로 초기화한 QSharedDataPointer를 구축합니다.

[explicit noexcept] QSharedDataPointer::QSharedDataPointer(T *data)

d 포인터를 data 로 설정하고 data 의 참조 수를 증가시키는 QSharedDataPointer를 생성합니다.

[noexcept, since 6.0] QSharedDataPointer::QSharedDataPointer(T *data, QAdoptSharedDataTag)

d 포인터가 data 로 설정된 QSharedDataPointer를 구축합니다. data 의 참조 카운터는 증가하지 않습니다; take()에서 얻은 포인터를 채택하는 데 사용할 수 있습니다.

이 함수는 Qt 6.0에 도입되었습니다.

take()도 참조하십시오 .

[noexcept] QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T> &o)

포인터를 od 포인터로 설정하고 공유 데이터 객체의 참조 횟수를 증가시킵니다.

[noexcept] QSharedDataPointer::QSharedDataPointer(QSharedDataPointer<T> &&o)

이동 - QSharedDataPointer 인스턴스를 생성하여 o 이 가리키던 것과 동일한 객체를 가리키도록 합니다.

QSharedDataPointer::~QSharedDataPointer()

공유 데이터 객체의 참조 개수를 감소시킵니다. 참조 카운트가 0이 되면 공유 데이터 개체가 삭제됩니다. 그러면 공유 데이터 개체가 소멸됩니다.

[protected] T *QSharedDataPointer::clone()

현재 데이터의 심층 복사본을 생성하고 반환합니다. 이 함수는 참조 카운트가 1보다 클 때 detach()에 의해 호출되어 새 복사본을 만듭니다. 이 함수는 new 연산자를 사용하고 T 유형의 복사본 생성자를 호출합니다.

이 함수는 자체 유형에 대해 "가상 복사본 생성자"를 지원할 수 있도록 제공됩니다. 그러기 위해서는 아래 예시와 같이 자체 유형에 대해 이 함수의 템플릿 특수화를 선언해야 합니다:

    template<>
    EmployeeData *QSharedDataPointer<EmployeeData>::clone()
    {
        return d->clone();
    }

위의 예에서 clone() 함수에 대한 템플릿 전문화는 EmployeeData::clone() 가상 함수를 호출합니다. EmployeeData에서 파생된 클래스는 해당 함수를 재정의하고 적절한 다형성 유형을 반환할 수 있습니다.

[noexcept] const T *QSharedDataPointer::constData() const

공유 데이터 객체에 대한 상수 포인터를 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

data()도 참조하세요 .

T *QSharedDataPointer::data()

공유 데이터 객체에 대한 포인터를 반환합니다. 이 함수는 detach()를 호출합니다.

constData()도 참조하세요 .

[noexcept] const T *QSharedDataPointer::data() const

공유 데이터 객체에 대한 포인터를 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

void QSharedDataPointer::detach()

공유 데이터 객체의 참조 수가 1보다 크면 이 함수는 공유 데이터 객체의 딥 복사본을 생성하고 복사본의 d 포인터를 복사본으로 설정합니다.

이 함수는 쓰기 시 복사가 필요한 경우 QSharedDataPointer 의 멤버 함수가 아닌 함수에 의해 자동으로 호출됩니다. 직접 호출할 필요가 없습니다.

[since 6.0] T *QSharedDataPointer::get()

data()와 동일합니다. 이 함수는 STL 호환성을 위해 제공됩니다.

이 함수는 Qt 6.0에 도입되었습니다.

[noexcept, since 6.0] const T *QSharedDataPointer::get() const

data()와 동일합니다. 이 함수는 STL 호환성을 위해 제공됩니다.

이 함수는 Qt 6.0에 도입되었습니다.

[noexcept, since 6.0] void QSharedDataPointer::reset(T *ptr = nullptr)

포인터를 ptr 로 설정하고 ptrnullptr 이 아닌 경우 ptr 의 참조 카운트를 증가시킵니다. 이전 공유 데이터 객체의 참조 카운트가 감소하고 참조 카운트가 0에 도달하면 객체가 삭제됩니다.

이 함수는 Qt 6.0에 도입되었습니다.

[noexcept] void QSharedDataPointer::swap(QSharedDataPointer<T> &other)

이 공유 데이터 포인터를 other 로 바꿉니다. 이 작업은 매우 빠르며 실패하지 않습니다.

[noexcept, since 6.0] T *QSharedDataPointer::take()

공유 객체에 대한 포인터를 반환하고 이를 nullptr 으로 재설정합니다(즉, 이 함수는 함수의 d 포인터를 nullptr 으로 설정합니다).

참고: 반환된 객체의 참조 카운트는 감소하지 않습니다. 이 함수는 QAdoptSharedDataTag 태그 객체를 받는 생성자와 함께 사용하여 원자 연산 개입 없이 공유 데이터 객체를 전송할 수 있습니다.

이 함수는 Qt 6.0에 도입되었습니다.

T *QSharedDataPointer::operator T *()

공유 데이터 객체에 대한 포인터를 반환합니다. 이 함수는 detach()를 호출합니다.

data() 및 constData()도 참조하세요 .

[noexcept] const T *QSharedDataPointer::operator const T *() const

공유 데이터 객체에 대한 포인터를 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

[noexcept] bool QSharedDataPointer::operator!() const

포인터가 nullptr 인 경우 true 을 반환합니다.

T &QSharedDataPointer::operator*()

공유 데이터 객체의 멤버에 대한 액세스를 제공합니다. 이 함수는 detach()를 호출합니다.

const T &QSharedDataPointer::operator*() const

공유 데이터 객체의 멤버에 대한 const 액세스를 제공합니다. 이 함수는 detach()를 호출하지 않습니다.

T *QSharedDataPointer::operator->()

공유 데이터 객체의 멤버에 대한 액세스를 제공합니다. 이 함수는 detach()를 호출합니다.

[noexcept] const T *QSharedDataPointer::operator->() const

공유 데이터 객체의 멤버에 대한 const 액세스를 제공합니다. 이 함수는 detach()를 호출하지 않습니다.

[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(QSharedDataPointer<T> &&other)

이동-이 other 인스턴스를 QSharedDataPointer 인스턴스에 할당합니다.

[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(T *o)

이것의 포인터를 o 로 설정하고 o 의 참조 수를 증가시킵니다. 이것의 이전 공유 데이터 객체의 참조 카운트는 감소합니다. 이전 공유 데이터 객체의 참조 카운트가 0이 되면 이전 공유 데이터 객체가 삭제됩니다.

[noexcept] QSharedDataPointer<T> &QSharedDataPointer::operator=(const QSharedDataPointer<T> &o)

이것의 d 포인터를 od 포인터로 설정하고 공유 데이터 객체의 참조 횟수를 증가시킵니다. 이것의 이전 공유 데이터 객체의 참조 카운트는 감소합니다. 이전 공유 데이터 객체의 참조 카운트가 0이 되면 이전 공유 데이터 객체가 삭제됩니다.

관련 비회원

[noexcept] bool operator!=(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)

lhsrhs 에 동일한 d 포인터가 없는 경우 true 을 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

[noexcept] bool operator!=(const T *ptr, const QSharedDataPointer<T> &rhs)

rhsd 포인터가 ptr. d 포인터가 아닌 경우 true 를 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

[noexcept] bool operator==(const QSharedDataPointer<T> &lhs, const QSharedDataPointer<T> &rhs)

lhsrhs포인터가 같으면 true 을 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

[noexcept] bool operator==(const T *ptr, const QSharedDataPointer<T> &rhs)

rhsd 포인터가 ptr 인 경우 true 을 반환합니다. 이 함수는 detach()를 호출하지 않습니다.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.