Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Fonctions  · 

Shared Classes

Many C++ classes in Qt use explicit and implicit data sharing to maximize resource usage and minimize copying of data.

Overview

A shared class consists of a pointer to a shared data block that contains a reference count and the data.

When a shared object is created, it sets the reference count to 1. The reference count is incremented whenever a new object references the shared data, and decremented when the object dereferences the shared data. The shared data is deleted when the reference count becomes zero.

When dealing with shared objects, there are two ways of copying an object. We usually speak about deep and shallow copies. A deep copy implies duplicating an object. A shallow copy is a reference copy, i.e. just a pointer to a shared data block. Making a deep copy can be expensive in terms of memory and CPU. Making a shallow copy is very fast, because it only involves setting a pointer and incrementing the reference count.

Object assignment (with operator=()) for implicitly and explicitly shared objects is implemented using shallow copies. A deep copy can be made by calling a copy() function or by using QDeepCopy.

The benefit of sharing is that a program does not need to duplicate data unnecessarily, which results in lower memory use and less copying of data. Objects can easily be assigned, sent as function arguments, and returned from functions.

Now comes the distinction between explicit and implicit sharing. Explicit sharing means that the programmer must be aware of the fact that objects share common data. Implicit sharing means that the sharing mechanism takes place behind the scenes and the programmer does not need to worry about it.

A QByteArray Example

QByteArray is an example of a shared class that uses explicit sharing. Example:

                          //Line    a=         b=         c=
    QByteArray a(3),b(2)  // 1:     {?,?,?}    {?,?}
    b[0] = 12; b[1] = 34; // 2:     {?,?,?}    {12,34}
    a = b;                // 3:     {12,34}    {12,34}
    a[1] = 56;            // 4:     {12,56}    {12,56}
    QByteArray c = a;     // 5:     {12,56}    {12,56}    {12,56}
    a.detach();           // 6:     {12,56}    {12,56}    {12,56}
    a[1] = 78;            // 7:     {12,78}    {12,56}    {12,56}
    b = a.copy();         // 8:     {12,78}    {12,78}    {12,56}
    a[1] = 90;            // 9:     {12,90}    {12,78}    {12,56}

The assignment a = b on line 3 throws away a's original shared block (the reference count becomes zero), sets a's shared block to point to b's shared block and increments the reference count.

On line 4, the contents of a is modified. b is also modified, because a and b refer to the same data block. This is the difference between explicit and implicit sharing (explained below).

The a object detaches from the common data on line 6. Detaching means that the shared data is copied to make sure that an object has its own private data. Therefore, modifying a on line 7 does not affect b or c.

Finally, on line 8 we make a deep copy of a and assign it to b, so that when a is modified on line 9, b remains unchanged.

Explicit vs. Implicit Sharing

Implicit sharing automatically detaches the object from a shared block if the object is about to change and the reference count is greater than one. (This is often called "copy-on-write".) Explicit sharing leaves this job to the programmer. If an explicitly shared object is not detached, changing an object will change all other objects that refer to the same data.

Implicit sharing optimizes memory use and copying of data without this side effect. So why didn't we implement implicit sharing for all shared classes? The answer is that a class that allows direct access to its internal data (for efficiency reasons), like QByteArray, cannot be implicitly shared, because it can be changed without letting QByteArray know.

An implicitly shared class has total control of its internal data. In any member functions that modify its data, it automatically detaches before modifying the data.

The QPen class, which uses implicit sharing, detaches from the shared data in all member functions that change the internal data.

Code fragment:

    void QPen::setStyle( PenStyle s )
    {
        detach();        // detach from common data
        data->style = s; // set the style member
    }

    void QPen::detach()
    {
        if ( data->count != 1 ) // only if >1 reference
            *this = copy();
    }

This is clearly not possible for QByteArray, because the programmer can do the following:

    QByteArray array( 10 );
    array.fill( 'a' );
    array[0] = 'f';        // will modify array
    array.data()[1] = 'i'; // will modify array

If we monitor changes in a QByteArray, the QByteArray class would become unacceptably slow.

Explicitly Shared Classes

All classes that are instances of the QMemArray template class are explicitly shared:

These classes have a detach() function that can be called if you want your object to get a private copy of the shared data. They also have a copy() function that returns a deep copy with a reference count of 1.

The same is true for QImage, which does not inherit QMemArray. QMovie is also explicitly shared, but it does not support detach() or copy().

Implicitly Shared Classes

The Qt classes that are implicitly shared are:

These classes automatically detach from common data if an object is about to be changed. The programmer will not even notice that the objects are shared. Thus you should treat separate instances of them as separate objects. They will always behave as separate objects but with the added benefit of sharing data whenever possible. For this reason, you can pass instances of these classes as arguments to functions by value without concern for the copying overhead.

Example:

    QPixmap p1, p2;
    p1.load( "image.bmp" );
    p2 = p1;                    // p1 and p2 share data
    QPainter paint;
    paint.begin( &p2 );         // cuts p2 loose from p1
    paint.drawText( 0,50, "Hi" );
    paint.end();

In this example, p1 and p2 share data until QPainter::begin() is called for p2, because painting a pixmap will modify it. The same also happens if anything is bitBlt()'ed into p2.

Warning: Do not copy an implicitly shared container (QMap, QValueVector, etc.) while you are iterating over it.

QCString: implicit or explicit?

QCString uses a mixture of implicit and explicit sharing. Functions inherited from QByteArray, such as data(), employ explicit sharing, while those only in QCString detach automatically. Thus, QCString is rather an "experts only" class, provided mainly to ease porting from Qt 1.x to Qt 2.0. We recommend that you use QString, a purely implicitly shared class.

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 64
  2. Apercevoir la troisième dimension ou l'utilisation multithreadée d'OpenGL dans Qt, un article des Qt Quarterly traduit par Guillaume Belz 0
  3. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  4. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  5. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
  6. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
  7. La rubrique Qt a besoin de vous ! 1
Page suivante

Le Qt Developer Network au hasard

Logo

Les composants

Le Qt Developer Network est un réseau de développeurs Qt anglophone, où ils peuvent partager leur expérience sur le framework. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 3.3
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web