C ++ std :: ref(T)与T&的区别

我有关于这个程序的一些问题:

#include <iostream> #include <type_traits> #include <functional> using namespace std; template <typename T> void foo ( T x ) { auto r=ref(x); cout<<boolalpha; cout<<is_same<T&,decltype(r)>::value; } int main() { int x=5; foo (x); return 0; } 

输出是:

 false 

我想知道,如果std::ref没有返回一个对象的引用,那么它是做什么的? 基本上有什么区别:

 T x; auto r = ref(x); 

 T x; T &y = x; 

另外,我想知道为什么这种差异存在? 当我们有引用(即T& )时,为什么我们需要std::refstd::reference_wrapper

那么ref构造一个适当的reference_wrappertypes的对象来保存一个对象的引用。 这意味着当你申请: –

 auto r = ref(x); 

这返回一个reference_wrapper &而不是直接引用x (ie T&) 。 这个reference_wrapper (ie r)代替T&

当你想模拟一个可以被复制的对象的reference (它既是可复制的,也可以是可复制的)时, reference_wrapper是非常有用的。

在C ++中,一旦你创build了一个object (say x) reference (say y)reference (say y) object (say x) ,那么yx共享相同的base address 。 此外, y不能引用任何其他对象。 你也不能创build一个array of references即像这样的代码会抛出一个错误:

 #include <iostream> using namespace std; int main() { int x=5, y=7, z=8; int& arr[] {x,y,z}; // error: declaration of 'arr' as array of references return 0; } 

不过这是合法的:

 #include <iostream> #include <functional> // for reference_wrapper using namespace std; int main() { int x=5, y=7, z=8; reference_wrapper<int> arr[] {x,y,z}; for (auto a:arr) cout<<a<<" "; return 0; } /* OUTPUT :- 5 7 8 */ 

cout<<is_same<T&,decltype(r)>::value;讨论你的问题cout<<is_same<T&,decltype(r)>::value; ,解决办法是:

 cout<<is_same<T&,decltype(r.get())>::value; // will yield true 

让我给你看一个节目:

 #include <iostream> #include <type_traits> #include <functional> using namespace std; int main() { cout<<boolalpha; int x=5, y=7;; reference_wrapper<int> r=x; // or auto r = ref(x); cout<<is_same<int&, decltype(r.get())>::value<<"\n"; cout<<(&x==&r.get())<<"\n"; r=y; cout<<(&y==&r.get())<<"\n"; r.get()=70; cout<<y; return 0; } /* Ouput :- true true true 70 */ 

看到这里我们知道三件事情:

  1. reference_wrapper对象(这里是r )可以用来创buildT&不可能array of references

  2. r实际上就像一个真实的reference (看看r.get()=70如何改变y的值)。

  3. rT&不相同,但r.get()是。 这意味着r持有T& ie,因为它的名称暗示了wrapper around reference T&

我希望这个答案足以解释你的疑惑。

std::reference_wrapper被标准设施识别为能够在按值传递的上下文中通过引用传递对象。

例如, std::bind可以接受std::ref() ,通过值传递它,并在稍后将其解压缩为一个引用。

 void print(int i) { std::cout << i << '\n'; } int main() { int i = 10; auto f1 = std::bind(print, i); auto f2 = std::bind(print, std::ref(i)); i = 20; f1(); f2(); } 

这段代码输出:

 10 20 

i的值已经存储(取值)到f1在它被初始化的点,但是f2已经保存了一个std::reference_wrapper的值,因此performance就像它在一个int&

引用( T& T&& )是C ++语言中的一个特殊元素。 它允许通过引用来操作对象并在该语言中有特殊用例。 例如,你不能创build一个标准的容器来保存引用: vector<T&>是不合格的,并产生一个编译错误。

std::reference_wrapper另一方面是一个C ++对象,能够容纳一个引用。 因此,您可以在标准容器中使用它。

std::ref是一个标准函数,它的参数返回一个std::reference_wrapper 。 在同样的想法中, std::crefstd::reference_wrapper返回给一个const引用。

std::reference_wrapper一个有趣的特性是它有一个operator T& () const noexcept; 。 这意味着, 即使它是一个真正的对象 ,它也可以自动转换为它所持有的引用。 所以:

  • 因为它是可复制分配的对象,所以可以在容器中使用,也可以在不允许引用的其他情况下使用
  • 由于它的operator T& () const noexcept; 它可以在任何可以使用引用的地方使用,因为它会自动转换为它。