这是一个非常简单的例子:
#include <iostream>
template<typename T>
void DoubleMe(T x) {
x += x;
}
int main()
{
int a = 10;
DoubleMe(a);
std::cout << a; //displays 10 not 20!
}
在这种情况下,我被迫使用&#39; T&amp;&#39;而在函数参数中呢? Cuz我在一些教程中读到模板可以正确地推导出适当的数据类型,包括T *,T []或T&amp;只需定义一个简单的T&#39;在变量之前。帮助
答案 0 :(得分:6)
是的,要获得您想要的效果,您必须添加&符号。
在编写时,模板可以正确推断数据类型。但是,他们可以推断出意图。在这种情况下,传递它的类型是一个整数,并且它正确地实例化一个整数函数,该函数在内部将按值传递给它的参数加倍。事实上,你认为函数有副作用,这不是编译器可以猜到的。
答案 1 :(得分:5)
您确实可以使用普通T
正确推断出引用类型。不幸的是,这并不意味着你的意思。
鉴于
template <typename T> struct S { };
template <typename T> void f(S<T>) { }
int main() { f(S<int&>{}); }
f
的类型参数被正确推导为int&
。
问题在于,在您的情况下,将T
推断为int
已经产生了完全有效的功能。也许稍微过度简化,但类型推导产生最简单的T
,使调用工作。在您的情况下,T = int
会使通话工作。不是你希望它的工作方式,但编译器无法知道。 T = int &
也可以使调用工作,但它不是最简单的T
使它工作。
答案 2 :(得分:4)
也许这会帮助你按照编译器的方式来看待它(如果我过分简化,可以向任何语言律师道歉):
&#xA;&#xA;在这个例子中,编译器必须推断T的类型是使函数声明合法且具有最小推论量的类型。由于T通常可以直接从const T&amp; amp; (这意味着它也可以从T&amp;复制构造),你的功能将采取副本。
&#xA;&#xA; template&lt; class T&gt;&#xA; void foo(T value); &#xA;
&#xA;&#xA; 在这个例子中,T必须是 ref
引用的对象的类型 - 并且因为引用不能参考引用,T必须是(可能是const,可能是易失性的)类型。
模板&lt; class T&gt;&#xA; void foo(T&amp; ref );&#xA;
&#xA;&#xA; 在这个例子中,ref必须引用类型为T的const(可能是易失性的)对象:
& #xA;&#xA; template&lt; class T&gt;&#xA; void foo(const T&amp; ref);&#xA;
&#xA;&#xA ; 在此示例中, ref
可以 作为参考或是r值引用。它被称为通用参考。您实际上是将两个函数合二为一,这通常是处理 ref
所有权的最有效方式。
template&lt; class T&gt;&#xA; void foo(T&amp;&amp; ref);&#xA;&#xA; //这样调用:&#xA; foo(Bar()); //表示ref将是一个&amp;&amp;&#xA;&#xA; //如下所示:&#xA; Bar b;&#xA; foo(b); //表示ref将是一个&amp;&#xA;&#xA; //这样调用:&#xA; const Bar b;&#xA; foo(b); //表示ref将是const Bar&amp;&#xA;
&#xA;&#xA; void foo(T value)
意味着我将复制你给我的任何内容。
void foo(T&amp; value)
表示我不会制作副本,但我可以修改您的值。 你可能不会给我一个临时的。
void foo(const T&amp; value)
意味着我不会制作副本,我无法修改您的副本。你可以给我一个临时的。
void foo(const T&amp;&amp; value)
意味着我可能窃取或者修改你的价值内容,即使它是暂时的。
答案 3 :(得分:0)
如果希望函数按值传递参数,则需要返回具有相同参数类型的值。
T DoubleMe(T x) {
return x + x;
}