我一直在研究更改一些代码以将 QStringBuilder 表达式模板用于purported performance improvements。不幸的是,这导致我的代码部分开始在某些地方崩溃,其示例如下:

#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确保强制转换在退出闭包之前进行。

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

最佳答案

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

[]() -> Type { }

or

[]() -> QString { }

关于c++ - 如何防止QStringBuilder超出其初始化范围,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32476634/

10-13 08:28