当您将结果保存为某种特殊类型时,通常会评估表达式模板,例如:
Result D = A*B+sin(C)+3.;
表达式的结果类型:
A*B+sin(C)+3.
不是Result,而是可以转换为Result的东西。并且评估发生在这种转换过程中。
我的问题是:是否有任何技术(例如,使用占位符?)来识别 D 的值实际上是未使用的
这种“转化”:
Result D = A*B+sin(C)+3.;
Result F = D*E;
到
Result F = (A*B+sin(C)+3.)*E;
当您不评估 D 时是可能的。为此,通常您应该将 D 捕获为真实的表达式类型。例如,在auto的帮助下:
auto &&D = A*B+sin(C)+3.;
Result F = D*E;
但是,您应该小心 - 有时表达式模板会捕获对其操作数的引用,并且如果您有一些在它的表达式之后会过期的右值:
auto &&D = A*get_large_rvalue();
// At this point, result of **get_large_rvalue** is destructed
// And D has expiried reference
Result F = D*E;
其中get_large_rvalue是:
LargeMatrix get_large_rvalue();
它的结果是rvalue,当get_large_rvalue被调用时,它在完整表达式的末尾到期。如果表达式中的某些内容将存储指向它的指针/引用(用于以后的评估)并且您将“推迟”评估 - 指针/引用将比指向/引用的对象寿命长。
为了防止这种情况,您应该这样做:
auto &&intermediate = get_large_rvalue(); // it would live till the end of scope
auto &&D = A*intermediate ;
Result F = D*E;
我不熟悉 C++11,但据我了解,auto 要求编译器从变量的初始化中确定变量的类型
对,就是这样。这称为类型推断/演绎。
C++98/03 仅对模板函数进行类型推导,在 C++11 中有auto。
你知道 CUDA 和 C++11 是如何交互的吗?
我没有使用过CUDA(虽然我使用过OpenCL ),但我猜想使用 C++11的主机代码不会有任何问题。设备代码中可能不支持某些 C++11 功能,但出于您的目的 - 您只需要在主机代码中使用auto
最后,只有 C++ 有可能吗?
你的意思是 C++11 之前的版本吗?即C++98/C++03?是的,这是可能的,但它有更多的语法噪音,也许这就是拒绝它的理由:
// somehwhere
{
use_D(A*B+sin(C)+3.);
}
// ...
template<typename Expression>
void use_D(Expression D) // depending on your expression template library
// it may be better to use (const Expression &e)
{
Result F = D*E;
}
我现在在 Windows 下使用 CUDA/Visual Studio 2010。您能否为两个操作系统推荐一个编译器/工具集/环境,以便在我感兴趣的框架中使用 C++11(GPGPU 和 CUDA,你知道吗)
MSVC 2010 确实支持 C++11 的某些部分。特别是它支持auto。所以,如果你只需要C++11 中的auto - MSVC2010 就可以了。
但是如果你可以使用 MSVC2012——我建议你坚持使用它——它有更好的 C++11 支持。
此外,技巧 auto &&intermediate = get_large_rvalue(); 似乎对第三方用户不是“透明的”(不应该知道这样的问题)。我对吗?有什么选择吗?
如果表达式模板存储了对某些值的引用,并且您推迟了它的评估。你应该确保它的所有引用在评估的地方都是有效的。使用您想要的任何方法 - 无需自动即可完成,例如:
LargeMatrix temp = get_large_rvalue();
甚至可能是全局/静态变量(不太喜欢的方法)。
最后的评论/问题:使用 auto &&D = A*B+sin(C)+3.; 看来我应该重载 operator= 以在两个表达式之间进行赋值,对吧?
不,这种形式既不需要复制/移动赋值运算符也不需要复制/移动构造函数。
基本上它只是命名临时值,并将其生命周期延长到范围的末尾。检查这个 SO。
但是,如果您要使用另一种形式:
auto D = A*B+sin(C)+3.;
在这种情况下,可能需要复制/移动/转换构造函数才能编译(尽管编译器可以使用Copy Ellision优化实际副本)
此外,在使用 auto (用于中间表达式)和 Result 之间切换以强制计算似乎对第三方用户不透明。有什么选择吗?
我不确定是否有其他选择。这是表达式模板的本质。当你在表达式中使用它们时——它们返回一些内部中间类型,但是当你存储到一些“特殊”类型时——评估被触发。