通过引用传递对象(将超出范围)

时间:2015-09-30 11:56:17

标签: c++ memory-leaks reference pass-by-reference undefined-behavior

所以我有这个功能:

addDataToList(..., QVariant metadata) { }

在这种情况下,相关的QVariant构造函数是:QVariant(const QString & val)

现在我有一个函数foo(),我可以在其中调用addDataToList()函数。 如何将有效值传递给QVariant对象?

如果我有这样的话:

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

它不起作用,因为str对象将超出范围,导致未定义的行为。

但是如果我在堆上创建字符串,就像这样:

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

它会起作用,但会有一些内存泄漏(因为QVariant没有取得传递指针的所有权。)

如何解决这种情况?

编辑:这是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();
        }
    }
}

2 个答案:

答案 0 :(得分:3)

使用

addDataToList(..., QVariant metadata) { }

您按价值获得QVariant。因此,您将复制传递给函数的值。所以在

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

您创建了一个临时QVariant,并将该临时内容复制到metadata中的addDataToList()。现在metadata是它自己的对象,并不依赖于你创建的临时对象。

答案 1 :(得分:2)

堆栈上具有临时对象的第一个版本将安全地工作,因为临时QString按值复制到QVariant - 不仅是参考。