C++ C++;标准::参考(T)和T&;之间的差异;?

C++ C++;标准::参考(T)和T&;之间的差异;?,c++,reference,ref,C++,Reference,Ref,关于这个项目,我有一些问题: #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&,decl

关于这个项目,我有一些问题:

#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;
}
我想知道,如果
std::ref
不返回对象的引用,那么它会做什么?基本上,以下两者的区别是什么:

T x;
auto r = ref(x);


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

std::reference\u 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();
}
<>代码> > 已被初始化(由值取值)到F1初始化时,但<>代码> f2>代码>按值保存了::RealthyTyWraseB/C++ >值,因此行为类似于<代码> INT/<代码>。

< P>参考文献(<代码> T&< /COD>或<代码> T&&<代码> >是C++语言中的一个特殊元素。它允许通过引用操作对象,并且在语言中有特殊的用例。例如,您无法创建标准容器来保存引用:
vector
格式错误并生成编译错误

A:Cord>STD::RealthyOnWrpuls<代码>另一方面是C++对象,它可以保存引用。因此,您可以在标准容器中使用它

std::ref
是一个标准函数,它在其参数上返回一个
std::reference\u包装
。在相同的思想中,
std::cref
std::reference\u包装器
返回常量引用

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

  • 由于它是一个副本可分配对象,因此可以在容器中或不允许引用的其他情况下使用它
  • 由于它的
    操作符T&()const noexcept,它可以在任何可以使用引用的地方使用,因为它将自动转换为引用

Well
ref
构造适当的
reference\u包装类型的对象,以保存对对象的引用。这意味着当你申请时:

auto r = ref(x);
这将返回一个
reference\u包装
,而不是对
x
(即
T&
)的直接引用。这个
reference\u包装器
(即
r
)反而保存着
T&

当您想要模拟可以复制的对象的
引用
时,
引用
包装非常有用(它既可以复制构造,也可以复制分配)

在C++中,一旦创建了一个引用(比如说代码> y>代码>)到一个对象(比如说代码> x<代码>),那么<代码> y>代码>和<代码> x >代码>共享相同的基地址。此外,
y
不能引用任何其他对象。此外,您不能创建引用数组,这样的ie代码将引发错误:

#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;
}
#包括
使用名称空间std;
int main()
{
int x=5,y=7,z=8;
int&arr[]{x,y,z};//错误:将'arr'声明为引用数组
返回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
*/
#包括
#包括//以供参考
使用名称空间std;
int main()
{
int x=5,y=7,z=8;
参考_包装器arr[]{x,y,z};
用于(自动a:arr)

提示不能重复:如果在这两种情况下都执行
x=y;
,会发生什么情况?除了我的重复标志(最后一条注释)之外:参见示例和@Ander,因为这不是关于有用性,而是关于差异mainly@CppNITR然后看看我在你发表评论前几秒钟链接的问题。特别是第二个问题很有用。@CppNITR当然!给我一点时间来组装一个小演示:)T&&ref(T)@CppNITR
std::ref(T)之间的区别是什么
返回一个
std::reference\u wrapper
。它只不过是一个包装好的指针,但库会将其识别为“嘿,我应该是一个引用!请在传递完我之后将我转回引用”。1:不,可以重新分配
reference\u wrapper
,但它不能“保留对多个对象的引用”.2/3:关于
.get()
在何处合适,这是一个公平的观点-但是在可以明确调用
r
的转换
操作符的情况下,无固定的
r
可以与
T&
一样使用,因此在许多情况下,包括在代码中的一些情况下,无需调用
.get()
(由于缺少空格,很难读取)。@underline\u d
reference\u wrapper
可以保存一组引用,如果您不确定,则可以自己尝试。另外
.get()
用于更改
reference\u wrapper
保存的对象的值`ie
r=70
是非法的,因此您必须使用
r.get()=70
。自己试试!!!!!不是真的。首先,让我们使用准确的措辞。您显示的是包含数组引用的引用包装,而不是本身包含“对多个对象的引用”的引用包装。包装器只保存一个引用。其次,我可以很好地获取数组的本机引用-你确定你没有忘记
inta[4]{1,2,3,4};int(&b)[4]=a;
?引用包装器在这里并不特殊,因为本机
t&
可以工作。@AnkitAcharya Yes:-)但准确地说,有效的结果放在一边,它本身只涉及一个对象。无论如何,你当然是对的,
包装器不同于普通的ref,它可以放在一个容器中。这很方便,但我认为人们误解了这一点,认为它比实际更先进。如果我想要一个“ref”数组,我通常会用
向量跳过中间人,这是
auto r = ref(x);
#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.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
*/