像往常一样,首先是代码:
#include <functional>
using namespace std;
using namespace std::tr1;
void f(int& r) { r++; }
template<class F, class P> void g1(F f, P t) { f(t); }
template<class F, class P> void g2(F f, P&& t) { f(forward<P>(t)); }
int main()
{
int i = 0;
g1(f, ref(i)); // old way, ugly way
g2(f, i); // new way, elegant way
}
在C ++ 98中,我们没有很好的方法通过模板函数来完善前向参数。因此,C ++大师发明了ref和cref来实现这一目标。
现在我们已经有了r值参考和完美转发,是否应该弃用ref和cref等?
答案 0 :(得分:3)
参考包装器仍然有用。这是关于存储东西的情况。例如,使用引用包装器,您可以使std :: make_tuple和std :: thread创建引用某些参数而不是复制它们的对象:
class abstract_job
{
public:
virtual ~abstract_job() {}
virtual void run() = 0;
};
class thread
{
public:
template<class Fun, class... Args>
thread(Fun&& f, Args&&... args)
{
typedef typename decay<Fun>::type fun_type;
typedef decltype( make_tuple(forward<Args>(args)...) ) tuple_type;
unique_ptr<abstract_job> ptr (new my_job<fun_type,tuple_type>(
forward<Fun>(fun),
make_tuple(forward<Args>(args)...)
));
// somehow pass pointer 'ptr' to the new thread
// which is supposed to invoke ptr->run();
}
...
};
...
void foo(const int&);
int main()
{
thread t (foo, 42); // 42 is copied and foo is invoked
t.join() // with a reference to this copy
int i = 23;
thread z (foo, std::cref(i)); // foo will get a reference to i
z.join();
}
请记住
make_tuple(std::ref(i)) // yields a tuple<int&>
make_tuple( i ) // yields a tuple<int>
干杯! 小号
答案 1 :(得分:2)
假设reference_wrapper
是为此而设的。相反,它似乎主要是允许通过引用传递函数对象,它们通常通过值来获取。 - 如果你把参数改为T&&
,那是不是意味着按价值传递东西变得不可能?
#include <iostream>
#include <functional>
#include <algorithm>
class X: public std::unary_function<int, void>
{
int n;
public:
X(): n(0) {}
void operator()(int m) {n += m;}
int get_n() const { return n; }
};
template <class Iter, class Fun>
void for_each(Iter from, Iter to, Fun&& fun)
{
for (; from != to; ++from)
fun(*from);
}
int main()
{
int a[] = {1, 2, 3};
X x1;
::for_each(a, a + 3, x1);
std::cout << x1.get_n() << '\n'; //6
X x2;
std::for_each(a, a + 3, x2);
std::cout << x2.get_n() << '\n'; //0
X x3;
std::for_each(a, a + 3, std::ref(x3));
std::cout << x3.get_n() << '\n'; //6
}