我已经看到了多个代码实例,其中函数参数包是使用&&表示法声明的,如下所示,但我看不出使用此表示法有什么好处。
template<typename... Args>
void Function(Args... args)
{
}
template<typename... Args>
void Function(Args&&... args)
{
}我的第一个想法是& form将专门用于r值对象,但这个测试证明了这一点是错误的:
struct Object
{
// Added bodies so I see what is being called via a step-into
Object() {}
Object(const Object&) {}
Object(Object&&) noexcept {}
Object& operator=(const Object&) { return *this; }
Object& operator=(Object&&) noexcept { return *this; }
};
Object GetObject() { Object o; return o; }
Object obj;
Function(GetObject());
Function(GetObject());在这里,VS 2017抱怨说,的这两种形式的函数是可行的候选调用。
有人能解释一下这两者之间的区别吗?请解释一下两者之间有什么优势?
发布于 2018-01-18 18:00:15
它们在参数包表单中转发引用。对于模板参数的推导,它们可以匹配任意参数,但模板参数的推导与普通模板参数不同。
转发引用的主要优点是,如果与std::forward一起使用,将保留lvalue/rvalue信息。因此,他们习惯于“转发”一些东西。
例如,
void real_foo(A const &a);
void real_foo(A &&a);
template<class... Args>
void foo_proxy_ordinary(Args... args) { real_foo(args...); }
template<class... Args>
void foo_proxy_perfect(Args&&... args) { real_foo(std::forward<Args>(args)...); }普通版本总是调用real_foo(A const &)版本,因为在foo_proxy中,args总是值。
但是,如果传入的参数确实是rvalue,则完美版本将选择real_foo(A&&)。
将转发引用和参数包相结合,可以方便地编写泛型代理函数,而不损失lvalue/rvalue的性能。
发布于 2018-01-18 18:01:44
的上下文中使用T&&。
template<typename T>
void f(T&& t);称为转发引用,有时也称为通用引用。
转发引用的主要优点是,与std::forward相结合,可以实现所谓的完美转发:函数模板将其参数按原样传递给另一个函数(lvalue作为lvalue,rvalue作为rvalue)。
现在可以创建以其他函数作为参数或返回参数的高阶函数,或者高级函数包装器(例如std::make_shared),并执行其他很酷的事情。
以下是一些比我能解释得更好、更详细的材料:
发布于 2018-01-18 18:00:36
有人能解释一下这两者之间的区别吗?请解释一下两者之间有什么优势?
参数包与单个参数的差别是相同的。Args声明了一个“对象参数”(按值传递),而Args&&声明了一个引用参数(通过引用传递)。
通过引用传递可以避免在没有必要时复制参数。如果引用是非const,则还允许修改所引用的参数,这包括从该对象移动的可能性。
传递的值使调用者清楚地知道,传递的对象既不会被修改,也不会因为调用函数而被引用。
我的第一个想法是& form将专门用于r-value对象。
正如您的测试所显示的,这确实是一个错误的假设。当Args是一个推导类型,即auto或模板参数时,Args&&确实可以是l值引用或r值引用。它是哪一个取决于推导出的Args是什么。这简要地说明了引用折叠规则:
typedef int& lref;
typedef int&& rref;
int n;
lref& r1 = n; // type of r1 is int&
lref&& r2 = n; // type of r2 is int& note this case in particular
rref& r3 = n; // type of r3 is int&
rref&& r4 = 1; // type of r4 is int&&使用这种引用允许转发,即重新绑定到一个新的lvalue引用(在可能的情况下)或从对象中移动(在可能的情况下)或复制(当前两者都不可能时)。
正因为如此,当Args&&是推断类型时,Args被称为转发引用(或通用引用)。
https://stackoverflow.com/questions/48327250
复制相似问题