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;

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

原文由 DevInd 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

那么 ref 构造一个适当的 reference_wrapper 类型的对象来保存对对象的引用。这意味着当您申请时:

 auto r = ref(x);

这将返回 reference_wrapper 而不是对 x 的直接引用(即 T& )。这 reference_wrapper (即 r )改为持有 T&

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

In C++, once you create a reference (say y ) to an object (say x ), then y and x share the相同的 _基地址_。此外, y 不能引用任何其他对象。您也不能创建 引用数组, 即这样的代码会引发错误:

 #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.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 )可用于创建 引用数组, 这是 T& 无法实现的。

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

  3. rT&r.get() 。这意味着 r 持有 T& 即顾名思义是 对引用 T& 的包装。

我希望这个答案足以解释您的疑问。

原文由 Ankit Acharya 发布,翻译遵循 CC BY-SA 4.0 许可协议

引用( T&T&& )是 C++ 语言中的一个特殊元素。它允许 通过引用 来操作对象,并且在语言中有特殊的用例。例如,您不能创建标准容器来保存引用: 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; ,它可以在任何可以使用引用的地方使用,因为它会自动转换为它。

原文由 Serge Ballesta 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题