Странный вопрос о конструкторе копирования для экземпляра типа QList - PullRequest
3 голосов
/ 16 мая 2019

Ниже приведен краткий обзор кода, чтобы продемонстрировать проблему, спасибо за ваше время.

  1. При RowOfData rowData = tableData[row]; будет вызван RowOfData конструктор копирования, который выполняет поверхностную проверкукопия.

  2. При tableData[row][col] = item; конструктор копирования QtParameter будет вызван операцией tableData[row][col], после чего будет вызван QList<T>::node_copy, поэтому новая запись tableData[row][col]будет назначен.

    • Вопрос: почему tableData[row][col] будет вызывать QtParameter конструктор копирования?

    • КСТАТИ, QtParameter копировать конструктор не будетне вызывается для tableData[row][col], когда в конце функции уничтожается rowData.

Классы:

            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;              
            }    

Функции-члены:

           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;
                    }
            ...
            }

1 Ответ

1 голос
/ 16 мая 2019

Возможна ситуация, когда функция-член TableData::setItem вызывается объектом типа QtParameter, поскольку функция берет его не по ссылке, внутри функции должен быть создан объект типа QtParameter путем конструирования копииот предыдущего!

Если вы хотите избежать этого, возьмите его по ссылке (желательно константный):

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

Двигаясь вперед, внутри функции по адресу:

RowOfData rowData = tableData[row];

С небольшой вероятностью, если это не какой-то тип / ы итератора / указателя на самом низком уровне, это также может быть источником.

Наконец, в:

tableData[row][col] = item;

На основании того, что вы упомянули, другой возможностью может быть способ определения самого оператора присваивания для класса tableData[row][col].Помня, что оператор присваивания также является функцией, если он не объявлен как:

assigned_to & operator=(const assigned_from &)

Например:

assigned_to & operator=(assigned_from)

То же, что и в первом случае, объект assign_from будеткопия, созданная в операторе присваивания.

Многие сведения не передаются, и, если под "Глубоким копированием" вы ссылаетесь на QList<T>::node_copy, конструктор копирования также может происходить внутри, просто по адресу:

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

Это явный вызов a конструктора копирования.Но поскольку информация о типах не указана, я не могу сказать наверняка, именно здесь вызывается конструктор копирования .

Кроме того, если вы не предоставите некоторую информацию о QList<QtParameter>, я мало что могу сказать о том, почему «Глубокое копирование» не произошло, когда была уничтожена rowData.

...