2

我一直在考虑更改一些代码以利用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或类似的表达式模板中,或者维护对自动变量的引用的对象总是不安全使用?

4

2 回答 2

0

clazy代码检查器为这种情况提供了检查

于 2017-11-17T16:51:03.293 回答
0

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

[]() -> Type { }

or 

[]() -> QString { }
于 2015-09-09T14:59:53.180 回答