Qt的相关Pointer(4)-------QSharedDataPointer

来源:互联网 发布:web后端编程语言 编辑:程序博客网 时间:2024/05/21 17:07

QSharedDataPointer


QSharedDataPointer可以指向一个隐式共享类对象。QSharedDataPointer<T>你可以很容易的实现自己的隐式共享类,QSharedDataPointer实现了线程安全的引用计数,从而保证了你自己写的可重入的隐式共享类不会因为加入QSharedDataPointer而变得不可重入。隐式共享应用在很多Qt类中,实现了速率和内存效率的有效结合,个人觉得这种思想就跟More Effective C++中 的Item17Consider using lazy evaluation差不多。

看看一下代码: Employee 是一个隐式共享类

 

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;

 };

 

 classEmployee

 {

  public:

    Employee() { d = new EmployeeData; }

    Employee(int id, 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(QString name) { d->name = name; }

   bool       operator==( const Employee & other ) const

       {

              if(d ==other.d)

              {

                     returntrue;

              }

              else

              {

                     returnfalse;

              }

       }

 

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

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

 

  private:

    QSharedDataPointer<EmployeeData>d;

 };

 

其中EmployeeData 必需继承自QSharedData,QSharedData类是共享数据的基类,它提供引用计数,它只有默认的构造函数,拷贝构造函数和析构函数,一般情况下,我们有必要自己重写这几个函数。Employee数据成员只有一个QSharedDataPointer<EmployeeData>指针,所以对d访问必须通过->方法。当我们需要改变d的数据时,如果d的引用计数大于1的话,将会调用detach()对d进行拷贝生成新的对象。从而保证了所以对d的改变,不会影响到别的引用。Employee对象被拷贝、用于赋值或者当成参数传递时,QSharedDataPointer指针的引用技术自动增加1;Employee对象被销毁或者超出作用域时,QSharedDataPointer指针的引用计数将自动减小1.当QSharedDataPointer引用计数为0时将自动销毁。

在这里将的拷贝都是深拷贝。

int main()
 Employee e1(1001, "Albrecht Durer");  Employee e2 = e1;

     if (e1 == e2)

       {

              qDebug("e1is equal e2 ");

       }

       else

       {

              qDebug("e1is not equal e2 ");

       }

       e1.setName("HansHolbein");

       if (e1 ==e2)

       {

              qDebug("e1is equal e2");

       }

       else

       {

              qDebug("e1is not equal e2 ");

       }

 
 }
当执行e2 = e1;e2和e1指向的是同一个对象,EmployeeData的引用计数变为2. e1和e2是相等的。执行e1.setName("Hans Holbein");时,由于将改变Employee对象的name,而且此时EmployeeData的引用计数变为2. e1和e2是相等的。执行e1.setName("Hans Holbein");时,由于将改变Employee对象的name,而且此时EmployeeData引用计数已经大于1,此时将进行写拷贝,e2和e1指向不同的EmployeeData对象,e1和e2的比较结果也将不再相等。e1和e2的ID均为1001,但e2的name变为Hans Holbein。

 

 

原创粉丝点击