为什么要使用参考而不是原始参考?

时间:2017-05-10 18:53:56

标签: c++ variables

这个问题可能看起来很主观,但实际上,我正在寻找一个客观原因,比如技术和逻辑部分。 因此,让我们为变量x:

声明一个别名
int x = 333;
int &xx = x;

为什么不使用x并省去创建别名/引用的麻烦?

4 个答案:

答案 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;