water
water

Reputation: 53

A strange question about copy constructor for QList type instance

Synopsis of a code is given below to demonstrate the problem, thanks for your time.

  1. At RowOfData rowData = tableData[row];, RowOfData copy constructer will be called and it performs a shallow copy.

  2. At tableData[row][col] = item;, QtParameter copy constructer will be called by tableData[row][col] assingment operation and it will be followed by a call to QList<T>::node_copy so the new entry tableData[row][col] will be assigned.

    • Question: why tableData[row][col] would call QtParameter copy constructer?

    • BTW, QtParameter copy constructer wouldn't be called for tableData[row][col] when rowData is destructed at the end of the function.

Classes:

            QtParameter::QtParameter( const QtParameter& rhs) :QVariant(rhs){}

            class RowOfData : QList<QtParameter>
            {
               public:
                  RowOfData(const RowOfData& rhs);                 
               private:            
            }

            class TableData
            {
               public :
                    TableData();
                    virtual ~TableData();
                    bool setItem(int row, int col, QtParameter item);                    
              protected:
                    QStringList         columnHeader;
                    QStringList         rowHeader;
                    QStringList         rowFooter;
                    QList< RowOfData >  tableData;              
            }    

Member functions:

           bool TableData::setItem(int row, int col, QtParameter item)
           {
              if(row<rowCount())     
               {                
                    RowOfData rowData = tableData[row];
            /*useless here and impact the tableData[row][col] copy constructer× */            
                    if( col < tableData.at(row).size() )
                    {
                        tableData[row][col] = item;
                    }
                }
            } 
            template <typename T>
            Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src)
            {
                Node *current = from;
                if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
                    QT_TRY {
                        while(current != to) {
                            current->v = new T(*reinterpret_cast<T*>(src->v));
                            ++current;
                            ++src;
                        }
                    } QT_CATCH(...) {
                        while (current-- != from)
                            delete reinterpret_cast<T*>(current->v);
                        QT_RETHROW;
                    }
            ...
            }

Upvotes: 3

Views: 300

Answers (1)

AKL
AKL

Reputation: 1389

One possibility is when member function TableData::setItem is called by an object of type QtParameter , because the function is taking it not by reference, an object of type QtParameter has to be created inside the function by copy constructing from the previous one!

If you want to avoid that, take it by reference (preferably const one) :

bool TableData::setItem(int row, int col, const QtParameter& item)

Moving forward, inside the function at:

RowOfData rowData = tableData[row];

With a small possibility, if these are not some type/s of iterator/pointer at their lowest level, this also could be the source.

Finally at:

tableData[row][col] = item;

Based of what you mentioned another possibility could be the way assignment operator itself is defined for the class of tableData[row][col]. Keeping in mind that assignment operator is also a function, if it is not declared like:

assigned_to & operator=(const assigned_from &)

For example:

assigned_to & operator=(assigned_from)

Same as the first case an object of assigned_from will be copy constructed inside the assignment operator.

Many information are not given and if by the "Deep copy" you are referring to QList<T>::node_copy, the copy constructor can also happen inside that simply at:

current->v = new T(*reinterpret_cast<T*>(src->v));

Which is a clear call to a copy constructor. But since information about the types are not given, I can't say for sure, this is where the copy constructor is called.

Also unless you provide some information about QList<QtParameter> , there is not much that I can say about why the "Deep copy" didn't take place when rowData was destructed.

Upvotes: 1

Related Questions