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();
}
<>代码> > 已被初始化(由值取值)到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代码>,它可以在任何可以使用引用的地方使用,因为它将自动转换为引用
Wellref
构造适当的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)@CppNITRstd::ref(T)之间的区别是什么
返回一个std::reference\u wrapper
。它只不过是一个包装好的指针,但库会将其识别为“嘿,我应该是一个引用!请在传递完我之后将我转回引用”。1:不,可以重新分配reference\u wrapper
,但它不能“保留对多个对象的引用”.2/3:关于.get()
在何处合适,这是一个公平的观点-但是在可以明确调用r
的转换操作符的情况下,无固定的r
可以与T&
一样使用,因此在许多情况下,包括在代码中的一些情况下,无需调用.get()
(由于缺少空格,很难读取)。@underline\u dreference\u wrapper
可以保存一组引用,如果您不确定,则可以自己尝试。另外.get()
用于更改reference\u wrapper
保存的对象的值`ier=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
*/