如何防止QStringBuilder超出其初始化的作用域

How to prevent QStringBuilder from outliving the scope it was initialised in

本文关键字:初始化 作用域 何防止 QStringBuilder      更新时间:2023-10-16

我一直在考虑改变一些代码,以利用QStringBuilder表达式模板来实现所谓的性能改进。不幸的是,这导致我的代码部分开始在某些地方崩溃,示例如下:

#define QT_USE_QSTRINGBUILDER
#include <numeric>
#include <vector>
#include <QString>
#include <QStringBuilder>
int main()
{
    std::vector<int> vals = {0, 1, 2, 3, 4};
    QString text = "Values: " + QString::number(vals[0]);
    text = std::accumulate(vals.begin() + 1, vals.end(), text, [](const QString& s, int i)
    {
        return s + ", " + QString::number(i);
    });
}

崩溃的原因是因为lambda表达式的返回类型被推断为QStringBuilder<QStringBuilder<QString,const char [3]>,QString>,在返回后试图强制转换为QString以分配给accumulate结果。这个强制转换会崩溃,因为它试图使用对lambda范围内的对象的引用,而这些对象现在已经被销毁了。可以通过显式指定lambda的返回类型(如[](const QString& s, int i) -> QString)来修复此崩溃,以确保在闭包退出之前进行强制转换。

然而,在这里启用QStringBuilder导致之前工作的代码崩溃,甚至没有发出警告,这意味着我现在将避免在其他地方使用它,除非我能保证这种情况不会再次发生。因为在这种情况下,RVO可以防止任何复制的发生,我不认为通常禁用对象复制的技术会起作用。是否有一种方法可以防止这种情况在QStringBuilder或类似的表达式模板中发生,或者是维护对自动变量的引用的对象总是不安全的?

lambda应该返回一个显式类型:

[]() -> Type { }
or 
[]() -> QString { }

clazy代码检查器为这个场景提供了一个检查