mariusmmg2
mariusmmg2

Reputation: 723

Pass object (that will go out of scope) by reference

So I have this function:

addDataToList(..., QVariant metadata) { }

The relevant QVariant constructor in this case is: QVariant(const QString & val).

Now I have a function foo(), from where I call addDataToList() function. How do I pass a valid value to the QVariant object?

If I have something like this:

void foo() {
    QString str = "String";
    addDataToList(..., QVariant(str));
}

It will not work because str object will go out of scope, leading into undefined behavior.

But if I create the string on heap, something like this:

void foo() {
    QString *str = new QString("String");
    addDataToList(..., QVariant(*str));
}

It will work, but there will be some memory leaks (because QVariant doesn't take ownership of the passed pointer).

How do I solve this situation?

EDIT: This is the actual implementation of addDataToList(...):

void TPMSvalidator::addDataToList(const QString &data, bool useMetadata, MessageTypes type, QVariant metadata) {
    QString text;
    QIcon okIcon(QDir::currentPath() + "\\Resources\\Icons\\ok3.png");
    QIcon notOkIcon(QDir::currentPath() + "\\Resources\\Icons\\notok.png");
    QIcon noticeIcon(QDir::currentPath() + "\\Resources\\Icons\\warning2.png");

    if (data != QString()) {
        QListWidgetItem *data_w = new QListWidgetItem;

        if (type == MessageTypes::notification) {
            data_w->setBackgroundColor(QColor(Qt::GlobalColor::gray));
            data_w->setTextColor(QColor(Qt::GlobalColor::black));
            data_w->setIcon(noticeIcon);
            text.append("NOTICE: ");
        }
        else if (type == MessageTypes::telegramOkInfo) {
            data_w->setBackgroundColor(QColor(Qt::GlobalColor::gray));
            data_w->setTextColor(QColor(Qt::GlobalColor::black));
            data_w->setIcon(okIcon);
            text.append("INFO: ");
        }
        else if (type == MessageTypes::telegramNotOkInfo) {
            data_w->setBackgroundColor(QColor(Qt::GlobalColor::gray));
            data_w->setTextColor(QColor(Qt::GlobalColor::red));
            data_w->setIcon(notOkIcon);
            text.append("INFO: ");
        }
        else if (type == MessageTypes::warning) {
            data_w->setBackgroundColor(QColor(Qt::GlobalColor::darkYellow));
            data_w->setTextColor(QColor(Qt::GlobalColor::black));
            text.append("WARNING: ");
        }
        else {
            data_w->setBackgroundColor(QColor(Qt::GlobalColor::darkRed).light(130));
            data_w->setTextColor(QColor(Qt::GlobalColor::white));
            data_w->setIcon(notOkIcon);
            text.append("ERROR: ");
        }

        text.append(data);
        data_w->setText(text);
        data_w->setFont(QFont("Helvetica"));

        if (useMetadata) {
            data_w->setData(Qt::UserRole, metadata);
        }

        ui.listData->addItem(data_w);

        if (ui.autoScrollCheckBox->isChecked()) {
            ui.listData->scrollToBottom();
        }
    }
}

Upvotes: 2

Views: 1392

Answers (2)

NathanOliver
NathanOliver

Reputation: 180630

With

addDataToList(..., QVariant metadata) { }

You are taking a QVariant by value. As such you will copy the the value passed to the function. So in

addDataToList(..., QVariant(str));

You create a temporary QVariant and the contents of that temporary are copied into metadata in addDataToList(). Now metadata is its own object and is not dependent on the temporary that you created.

Upvotes: 3

Juraj Blaho
Juraj Blaho

Reputation: 13451

The first version with temporary object on the stack will work safely, because the temporary QString is copied by value into the QVariant - not only the reference.

Upvotes: 2

Related Questions