Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Why QByteArray decreasing capacity on resize to smaller size? How to force it to keep capacity?



  • #include <iostream>
    #include <QByteArray>
    #include <vector>
    
    
    
    int main(int argc, char *argv[])
    {
        QByteArray bytes;
        std::vector<int> vec;
        bytes.resize(5000);
        vec.resize(5000);
        std::cout<<"QByteArray capacity: "<<bytes.capacity()<<" std::vector capacity: "<<vec.capacity()<<std::endl;
        bytes.resize(10);
        vec.resize(10);
        std::cout<<"QByteArray capacity: "<<bytes.capacity()<<" std::vector capacity: "<<vec.capacity()<<std::endl;    
        return 0;
    }
    

    Output for me is:

    QByteArray capacity: 5000 std::vector capacity: 5000
    QByteArray capacity: 39 std::vector capacity: 5000
    

    I was very surprised. How to force QByteArray keep it's capacity?



  • @Sacha_D

    Well QVector::resize says:
    Since Qt 5.6, resize() doesn't shrink the capacity anymore. To shed excess capacity, use squeeze().

    Obviously this "feature" did not make it to QByteArray.

    However, why doing a resize for shinking the size when the capacity shall be maintained?

    For QVector this makes sense when you require a specific number of entries (e.g. geometric vectors).



  • @koahnig I send messages via QUDPSocket. I have a message with various length and fill it with data. If capacity is keeped, I can reserve to max capacity what I need and then fast fill it without reallocation to any size. After that call resize and send. I could also use a pointers to data fields in it, because it will not be reallocated and pointers lasts valid all time.

    void ServerBugProc::prepareBugs(){
        sendBugsMsg.resize(sendBugsMsgMaxSize);//Now I need this !!!
        quint8 *ptr = reinterpret_cast<quint8*>(sendBugsMsg.data());
        ptr+=2;
        static ServerTimeState * srvStates [BugProtocol::f08_framesCount];    
        tsBuffer.lastStates(*ptr, srvStates,BugProtocol::f08_framesCount);
        ++ptr;
        int msgSize = 3;
        for (quint8 i = 0; i < BugProtocol::f08_framesCount; ++i){
            quint8 *bugsInTimeMomentToSend_ptr = ptr;
            ++ptr;
            ++msgSize;
            quint8 bugsInTimeMomentToSend = 0;
            for (quint8 j = 0; j < gameInitFields.bugCount; ++j){
                if (srvStates[i]->bugs[j].state() == ServerBug::Hidden)
                    continue;
    
                memcpy(ptr, srvStates[i]->bugs[j].data, ServerBug::serializedSize);
                ptr+=ServerBug::serializedSize;
                msgSize += ServerBug::serializedSize;
                ++bugsInTimeMomentToSend;
            }
            *bugsInTimeMomentToSend_ptr = bugsInTimeMomentToSend;
        }
    
        sendBugsMsg.resize(msgSize);//suggested to be safe, because capacity must lasts and object does not moves in memory
    }
    
    
    

  • Moderators

    @Sacha_D
    have you tried void QByteArray::reserve(int size) seems like that would do what you want it to?



  • @J-Hilk, Thank you.

    int main(int argc, char *argv[])
    {
        QByteArray bytes;
        std::vector<int> vec;
        bytes.resize(5000);
        bytes.reserve(5000);
        vec.resize(5000);
        std::cout<<"QByteArray capacity: "<<bytes.capacity()<<" std::vector capacity: "<<vec.capacity()<<std::endl;
        bytes.resize(10);
        vec.resize(10);
        std::cout<<"QByteArray capacity: "<<bytes.capacity()<<" std::vector capacity: "<<vec.capacity()<<std::endl;
        return 0;
    }
    
    
    QByteArray capacity: 5000 std::vector capacity: 5000
    QByteArray capacity: 5000 std::vector capacity: 5000
    

Log in to reply