假设我有以下简单的Vector类:
template <class N>
class Vector<N>
{
public:
std::array<int, N> a;
};
我在double
的第一次尝试如下:
template <class N>
Vector<N>&& double1(Vector<N>&& x)
{
for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
return static_cast<Vector<N>&&>(x);
}
这最初看起来不错,但如果我这样做:
auto x&& = double1(makeVector(1,2,3))
我会提到临时问题。
我的第二次尝试如下:
template <class N>
Vector<N> double2(Vector<N>&& x)
{
for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
return x;
}
这似乎没有对临时问题的上述引用,但我认为这是一个不必要的移动/复制返回。
我可以通过执行以下操作来避免引用临时问题和额外移动/复制:
template <class N>
void double3(Vector<N>& x)
{
for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
}
但是我必须对这个论点进行修改,我觉得这有点凌乱。我还要指出临时工。
我的最终想法如下:
template <class N>
Vector<N> double4(Vector<N> x)
{
for (int i = 0; i != N, ++i) { x.a[i] *= 2; }
return x;
}
如果参数存储在与结果相同的位置,那么会避免所有副本,但我不知道如何执行此操作。
基本上我正在寻找具有以下属性的双重功能:
(1)在分配auto时没有引用临时问题 (2)临时通过时不得复印件 (3)传递非临时参数时不修改参数。
任何人都知道如何把这三件事放在一起?
修改
或许更简单地说,这就是我想要的行为。
(1)如果参数是临时的,请将其修改到位 (2)否则,复印一份。
答案 0 :(得分:2)
你的最终想法是正确有效的,请继续使用:
template <class N>
Vector<N> double4(Vector<N> x)
{
for (int i = 0; i != N, ++i) { x[i] *= 2; }
return x;
}
答案 1 :(得分:1)
此代码没有意义。
首先,std :: array采用两个模板参数:类型和大小。其次,std :: array是一个聚合;它真的不可动。可以移动内容,但不能移动对象本身。
第三,你滥用r值引用没有明显的收益。如果你想要加倍,只需使用常规引用,就像在C ++ 0x之前一样。
但是我必须对这个论点进行修改,我觉得这有点凌乱。我还要指出临时工。
实际存储对象没有任何问题。并非一切都需要是暂时的。如果除了C ++不允许的其他原因之外,通过尝试暂时通过函数调用来获得绝对没有效率。
关于更改参数并没有什么“混乱”; C ++不是一种函数式语言。
哦,r值引用不是“临时引用”。他们可以引用临时工,但这不是他们唯一做的事情。