这个问题可能看起来很主观,但实际上,我正在寻找一个客观原因,比如技术和逻辑部分。 因此,让我们为变量x:
声明一个别名int x = 333;
int &xx = x;
为什么不使用x并省去创建别名/引用的麻烦?
答案 0 :(得分:2)
我们不要声明它。在这种情况下,您只需使用x
。
然而,当你处理大型对象,比如巨大的类,甚至是巨大的向量时,你不想复制整个东西,这就是你将引用传递给需要该类/对象/无论什么的函数的原因
传递或返回对象作为函数参数按引用而不是按值
可能是最重要的原因。有关详情,请阅读Why should I use reference variables at all?
答案 1 :(得分:2)
除了gsamaras所说的,当您想要修改某些内容时,可以使用引用
std::vector<int> myvector{ 1,2,3,4,5 };
for (auto& elem : myvector) ++elem;
答案 2 :(得分:1)
您是否正在寻找在块范围内使用引用而非对象的充分理由?
引用绑定到对象并允许另一种方法来识别它们。在您的示例中保存333的变量,实质上只有两个名称。如果你看一下生成的程序集,你可能甚至不会看到除了对象之外的任何东西的分配。例如,此代码:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
std::srand(std::time(NULL));
int x = std::rand();
int &xx = x;
++xx;
std::cout << xx;
return 0;
}
在启用优化时生成此程序集:
main:
sub rsp, 8
mov edi, 0
call time
mov edi, eax
call srand
call rand
lea esi, [rax+1]
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
add rsp, 8
ret
_GLOBAL__sub_I_main:
sub rsp, 8
mov edi, OFFSET FLAT:std::__ioinit
call std::ios_base::Init::Init()
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:std::__ioinit
mov edi, OFFSET FLAT:std::ios_base::Init::~Init()
call __cxa_atexit
add rsp, 8
ret
如果您在live example处查看此内容并查看哪些代码映射到哪里,您会注意到绝对没有剩余参考的代表。所有访问都是对象。
因此,如果块范围内的引用只是为对象赋予另一个名称的一种奇特方式,那么它并不是那么有用。但是,如果该对象没有名称可以开始呢?
例如:
std::string foo() { return "Hello World!"; }
int main() {
foo();
}
当我调用foo
时,它会返回存储结果的临时对象。那个对象是无名的。我可以直接使用它,也可以在通话后达到;
的纳秒时间。当然,我可以复制它:
std::string res = foo();
但是,如果字符串很长,我只想打印几次。为什么我不得不把时间浪费在副本上?
原来你不必复制:
std::string const &res = foo();
以上是不是悬挂参考! const引用可以绑定到临时对象。并且C ++语言承诺,只要引用在该块作用域中,该对象就会存在。基本上,我们可以命名对象并在调用后使其可用,从而保存副本。
答案 3 :(得分:1)
除了其他答案中描述的函数调用和循环用法之外,我还想使用引用来避免重复引用深层嵌套结构。
所以不要写
collection.container[i].subcontainer->item.func_a();
collection.container[i].subcontainer->item.func_b();
collection.container[i].subcontainer->item.data = d;
我有时会使用
auto & cur_item = collection.container[i].subcontainer->item;
cur_item.func_a();
cur_item.func_b();
cur_item.data = d;