Qt i Implicit Sharing

0

Jakiś czas temu doczytałem, iż wiele klas Qt jest implicit sharing .. mniej więcej rozumiem to 'zjawisko' (w skórcie: nie jest przekazywana kopia (przez wartość) ale sam wskaźnik; i zwiększany jest tzw. refcount), ale chciałbym się odnieść do konkretnych przypadków użycia..

Mam powiedzmy taki kod: (nie ma on za bardzo sensu 'logicznego', ale nie musi mieć .. :) )

 QList<QVariant> function(QStringList list)
{
    QList<QVariant> l;
    ...
    if(list.at(2) == l.at(2))
        return l;
}

Z wiedzy, którą na ten moment posiadam (klasy QStringList i QList są implicit sharing ) to zarówno na zmiennej list jak i zwracanej l operacje będą wykonywane poprzez wskaźnik, tak ? (czyli będzie zachowana swoista oszczędność pamięci ?)

A czy zapis w/w kodu z operatorami referencji & coś zmienia:

 QList<QVariant>& function(const QStringList& list)
{
    QList<QVariant> l;
    ...
    if(list.at(2) == l.at(2))
        return l;
}

? (bo w przypadku 'czystego' C++ ten drugi zapis jest bardziej odpowiedni..)

0

Up
// bardzo niechętnie podbiję wątek, ale nadal jestem ciekaw zdania forumowiczów znających temat.. (a w międzyczasie były Święta i wielu osób mogło nie być i nie widzieć wątku ;)

2

Pomijając fakt poważnego błędu w drugiej wersji (zwracana referencja do obiektu lokalnego - automatycznego):
Zmiana polega na tym, że w drugim przypadku refcount nie jest zmieniany. Taki kod powinien być szybszy (jest jakiś koszt wykonania płytkiej kopii).
Poza tym, druga wersja całkowicie blokuje możliwość wykonania pełnej kopii (kompilator tego dopilnuje).
W pierwszej wersji jeśli ktoś np użyje operatora [], to spowoduje nieintencjonalne i automatyczne wykonanie pełnej kopii.

przekazywanie dużych obiektów przez wartość jest ogólnie złą praktyką, nawet jeśli stosują one Copy on Write i Implicit Sharing.
Nawet w źródłach Qt nie znajdziesz czegoś takiego (no może pojedyncze przypadki).

0

Dodam jeszcze że return musi być w każdym przypadku.

0

@MarekR22 - dzięki za odpowiedź. Odnośnie złej praktyki przekazywania dużych obiektów przez wartość.. to słyszałem o tym..

Chciałbym jednak wtedy zapytać jak poprawnie miałaby wyglądać 'ogólna postać' metody, odpowiedzialna za wykonywanie i zwracanie wyników pobranych z bazy danych?

Na ten moment mam przygotowaną następującą metodę:

 
QList<QVariantList> DBClass::SelectByProcedure(QString const& querytext, QList<QVariant> const& arg)
{
    QSqlQuery query;
    query.prepare(querytext);

    for (int i=0; i<arg.count();i++)
        query.bindValue(i,arg.at(i));

    if (!query.exec()) {
        qDebug() << query.lastError().text();
    }

    QList<QVariantList> tab;

    if (query.size() > 0 )
    {
        while (query.next())
        {
           QList<QVariant> record;
           for(int i=0; i< query.record().count(); ++i)
              record.append(query.value(i));

           tab.append(record);
        }
    }
    else
    {
        qDebug() << "query error";
    }

    return tab;
}

Jak powinna wyglądać jej **poprawna **postać? (chodzi mi przede wszystkim o kwestie związanie z zarządzaniem pamięcią..)

1 użytkowników online, w tym zalogowanych: 0, gości: 1