QList::insert issue...



  • Hello,
    I have written a code in which i have a problem in using QList::insert function.

    @
    #include <QCoreApplication>
    #include <QList>
    #include <QDebug>

    int main(int argc, char* argv[])
    {
    QCoreApplication app(argc, argv);
    QList<QVariant> paramList;

    paramList.reserve (10);
    paramList.insert(0, "text 0");
    paramList.insert(5, "text 5");
    
    qDebug() << "string  0:" << paramList.value(0);
    qDebug() << "string  5:" << paramList.value(5);
    
    return app.exec();
    

    }
    @

    this gives me output like,
    string 0: "text 0"
    string 5: ""

    so is it that i can't store string values to this QList at random location [within max element range..] .???



  • @QList<QString> paramList;@



  • Your list is initially empty, reserve does not change its size, only its capacity. The first insert is working only because the index is 0.

    You should use resize instead.



  • [[Doc:QList]] doesn't have a resize() method. [[Doc:QVector]] seems to be the better class for your use case, it has resize or you can set an initial size on construction of the vector.



  • what if i want to go with QLIst<QVariant>.??
    because i want to store mixed data types, strings as well as integers...

    is it like, if i have fixed amount of data then i need to initialize all of them before inserting data at random index.??


  • Moderators

    No. But if you want to reserve memory, the container (compiler, etc. depending on the details) needs to know in advance, how much memory is needed. If you store items of different size, it cannot be done automatically (ok I'm simplifying a bit). If you really need random indexes, I would suggest:

    Use QVariant pointer - this way the size of the item is fixed.

    Or - IMO the easiest and most flexible - use QMap (for example QMap<int, QString>).



  • This is absolutely right and there is nothing wrong. reserve() doesn't change the size() of QList, which will be changed for every insert() call. Having said that, after the first insert() call the size() will be incremented. Now for the second call, since 5 < current size() of 1, it will be appended and again the size() will be incremented to 2 now.

    If you dump qDebug() << "string 1:" << paramList.value(1); you can see that "text 5" is appended there.

    "QList::insert()":http://qt-project.org/doc/qt-4.8/qlist.html#insert

    I presume it doesn't matter whether it is QVariant or QString, the behavior would be the same.

    Now am curious to know, why would you insert() at an index which isn't there in the list. If you would want to add, use append() call to add to the list. Normal procedure to use insert() call is to insert a record to an index which is already available in the QList<>. Just curious.



  • [quote author="aekam" date="1335498222"]what if i want to go with QLIst<QVariant>.??
    because i want to store mixed data types, strings as well as integers...

    is it like, if i have fixed amount of data then i need to initialize all of them before inserting data at random index.??[/quote]

    You can store mixed data types in a [[Doc:QVector]]<[[Doc:QVariant]]>. Or use the suggested [[Doc:QMap]] approach in case your container is only sparsely filled.



  • @volker
    Qt document suggests using the QList instead of the QVector class. The Qlist is faster and expands to less code. You only need the QVector if you need adjacent variables in your memory.
    The QMap is the way to go I think.



  • And what if QList does not allow what you want to do? Right: use a different class!

    Wether this is QMap or QVector depends and it is up to the developer to decide this, as he/she is the only one who knows the use case, whether the container is full or only sparsely filled, etc. etc.



  • QList document says, Use this function to avoid repetetive reallocation of QList's internal data if you can predict how many elements will be appended. Note that the reservation applies only to the internal pointer array.

    what i understood from this is that reserve does pre-allocation only for internal pointer array and not for the actual elements [even though size is known, except in case of strings and variants].

    then what is the advantage of using reserve.??
    I am little bit confused between first and second statements of the documents mentioned above.



  • @
    QList<QVariant> paramList;

    typedef enum
    {
        ACTIVITY_TYPE = 0,
        PARAM_0,
        PARAM_1,
        PARAM_2,
        MAX_PARAM
    }ListIndex_e;
    

    @

    @Veeraps:
    what i require is to have a QList of QVariant type, which holds parameters of different kind.
    first element of List will always specify type of activity, from which i will need to decide which parameters to read or write in list. so i thought it would be good if i can read or write only the index of the interest, in random order.



  • [quote author="aekam" date="1335786053"]
    what i understood from this is that reserve does pre-allocation only for internal pointer array and not for the actual elements [even though size is known, except in case of strings and variants].[/quote]

    Each time the internal array is resized, a completely new array is allocated and the existing data must be copied to the new chunk of memory. This is a more or less costly operation. If you know the number of elements in advance, you can tell QList to preallocate enough memory so that all entries can be stored. You avoid copying around stuff and speed up the creation of the array a little bit.



  • bq. Volker wrote:
    Each time the internal array is resized, a completely new array is allocated and the existing data must be copied to the new chunk of memory. This is a more or less costly operation. If you know the number of elements in advance, you can tell QList to preallocate enough memory so that all entries can be stored. You avoid copying around stuff and speed up the creation of the array a little bit.

    Completely agree with Volker

    STL use the same mechanism to reserve the memory in advance is total size is known to avoid costly resize while the list is getting populated. Remember append() or insert() will also increase the size of the List if sufficient size is not available. This will recreate the whole chunk of memory, which is costly. This is why STL introduced reserve(). Since Qt Templates are closer and presume written in same way as STL, they would have also included the same mechanism.



  • @
    QList<QVariant> paramList;

    typedef enum {
    ACTIVITY_TYPE = 0,
    PARAM_0,
    PARAM_1,
    PARAM_2,
    MAX_PARAM
    } ListIndex_e ;
    @

    bq. aekam wrote:
    @Veeraps:
    what i require is to have a QList of QVariant type, which holds parameters of different kind.
    first element of List will always specify type of activity, from which i will need to decide which parameters to read or write in list. so i thought it would be good if i can read or write only the index of the interest, in random order.

    Is there a one-to-one mapping between the enum ListIndex_e and paramList? i.e., paramList will contain MAX_PARAM + 1 elements?

    Since you mentioned that based on ACTIVITY_TYPE, you select particular PARAM for read/write. What will you do if the PARAM isn't available (this is what the error that you already mentioned in this thread) ? or is it assumed that all PARAMs will exist? I would suggest you to add dummy PARAM in the list (even if it is not used at the missing indices).



  • bq. Veeraps wrote:
    I would suggest you to add dummy PARAM in the list (even if it is not used at the missing indices).

    Yes as of now I am filling all the parameters, even if it is not required...


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.