表达式模板通常用作一种优化技术,以避免创建临时对象。他们推迟构造完整的对象,直到模板用于赋值或初始化。这可用于字符串构建器、线性代数包等。
为了避免昂贵的副本,表达式模板类可以通过引用捕获更大的参数。我将以 QtQStringBuilder
为例。
当引用超过表达式模板时,它可以工作:
QString foo = QString("A") + QString("B");
^^^^^^^^^^^^^^^^^^^^^^^^^^^
QStringBuilder<QConcatenable<QString>,
QConcatenable<QString>>
表达式模板的转换和解析发生在赋值时。字符串临时对象的寿命超过了分配。
唉,一旦推断出表达式模板类型而不是目标类型,我们就会遇到麻烦:
// WORKS
QString foo = []() -> QString { return QString("A") + QString("B"); }();
// FAILS
QString foo = []{ return QString("A") + QString("B"); }();
并且:
auto foo = QString("A") + QString("B");
// foo holds references to strings that don't exist anymore
QString bar = foo; // oops
一种解决方案是让构建器保存对象的副本。由于QString
这里的 s 是隐式共享的,因此它们的复制很便宜,尽管仍然比持有引用更昂贵。但是,假设参数是std::string
:除非必要,否则您绝对不想复制它们。
有没有什么技术可以用来检测一个完整的模板表达式没有立即解析,并且必须复制数据到目前为止只持有一个引用?
注意:我不是在询问表达式模板的任何特定现有实现。我只QStringBuilder
用作一个激励的例子。这不是 Qt 问题,也不是特征问题等。标题就是问题,差不多。