【发布时间】:2015-12-05 06:00:41
【问题描述】:
我一直在考虑更改一些代码以将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 会导致以前工作的代码崩溃,甚至没有发出警告,这意味着我现在将避免在其他地方使用它,除非我能保证这种情况不会再次发生。由于在这种情况下,RVO 可以防止发生任何复制,我认为禁用对象复制的常用技术不会起作用。有没有办法防止在QStringBuilder 或类似的表达式模板中发生这种情况,或者维护对自动变量的引用的对象总是不安全使用?
【问题讨论】:
-
这是一个 Qt 错误。如果还没有提交,请提交,它应该很快就会修复。
-
QStringBuilder与 C++11 兼容,但目前不与 C++14 兼容……这本质上是一个 C++14,而不是 C++11 问题。 -
@KubaOber 在 C++11 中不需要指定带有单个 return 语句的 lambda 表达式的返回类型,这就是导致此问题的原因。
-
@KubaOber 这个错误has already been filed 并作为“超出范围”关闭。
标签: c++ qt c++11 expression-templates