函数返回非引用变量和引用变量之间的差异

时间:2014-06-18 13:37:07

标签: c++ reference pass-by-reference

考虑以下代码

int& func1() {
    int x = 2;
    return x;
}

int& func2(int &x) {
    return x;
}

int main() {
    int x = func1();
    cout<<"\n : "<<x;
    int y = 3;
    x = func2(y);

    cout<<"\n : "<<x<<"\n";
}

输出:

 : 2
 : 3

代码工作正常,但我对下面列出的内容几乎没有疑问:

  1. 在func1()中,我返回了一个non_reference变量&#34; x&#34;但是 return类型是对int的引用,所以如何转换 发生了什么以及&#34; x&#34;功能实际上正在返回。

  2. 在func1()&#34; x&#34;作为参考返回但是作为堆栈变量如何引用 可以返回x ,我的意思是它在完成后没有任何意义(我 我将这一点与逻辑相关联。函数不应返回其指针 内存以静态方式分配&#34;)。

  3. 在func1()中,它返回一个非参数变量&#34; x&#34;作为参考 到一个int和在func2()中它返回一个引用变量&#34; x&#34;如 参考int。 同时&#34; x&#34;是不同类型,但为什么 返回类型相同。

  4. 我很困惑,因为我试图将C ++与c联系起来,因为一切都很清楚,但这主要是由于缺乏refrence变量的内存布局描述,所以如果有人能说明这一点那么它将会非常有帮助我

2 个答案:

答案 0 :(得分:3)

func1中,你要归的是对某事的引用。这个内容是x,它是func1的本地内容,其生命周期在返回时结束。然后,在main中,您分配引用变量的内容(x func1,它正在根据吃蒲公英)来初始化main的本地变量x。这是未定义的行为,这意味着允许程序将其解释为它想要的任何内容,格式化您的硬盘驱动器或任何东西。 (最有可能的是,func1返回指向被调用堆栈帧的变量的指针,该变量可能仍然包含正确的值,因为当它们被下一个函数调用压碎时,为什么还要删除堆栈上的值呢? )无论如何,程序是否会与其他优化选项一起编译,它可能会给出另一个答案。

func2中,你要归的是对某事的引用。 x引用的内容是main y引用的内容。然后,您为main的{​​{1}}分配了引用变量的值x

关于引用的内存布局问题,在C中,指针是内存中的地址。期。无处可逃。在C ++中,引用是一种更高级别的机制,在这种机制中,您“引用某些东西”,“谈论某些东西”,“看起来就是我就在那里”。 它们完全可以作为普通指针实现。但作为一种语言概念,它们更容易被优化掉,因为它们是不可变的。 (一旦设置了引用,它就无法更改。它指的是某些内容 - 甚至是无效内存位置的对象)这就是标准没有为引用指定存储空间的原因。为了优化自由。

更新:关于您的第一个疑问,y的{​​{1}}是一个完整的变量(它被声明为这样)而不是参考。因此,为其指定任何其他值都不会改变main的值。在C ++中,当您在表达式中评估引用时,如下所示:

x

它被评估为所引用变量的值,即y的值,即int x = 0; int& y = x; // Right hand side is the evaluation of the reference y int z = y; x是一个与0不同的变量。

关于您的第三个疑问,z将返回引用。当函数声明为返回引用时,它返回的是引用。引用的内容是“我就是那边的另一个”。在返回值的情况下,在汇编程序级别,如果函数未内联且调用确实发生,依此类推,xfunc2最有可能返回的内容将是指向引用变量的指针。实际上,在C ++中,对func1的引用是通过使用func2推导int指针而得到的类型。将前面的示例代码与带有指针的相同代码进行比较。

int

通过引用,*int x = 0; int* const y = &x; int z = *y; 会无声地发生。

您知道,已经在语言中引入了引用以支持运算符重载,尤其是赋值运算符。

&

它不能是一个值,也不会表现得非常糟糕(通过副本传递结果)。它必须是某种指针,但它不可能。某处会有*// Quizz : what is the type of (b = A(123))? What if it is a 1MB object? // What should be the type of the right-hand side of the assignment operator? A a, b; a = b = A(123); ,具体取决于您如何使用Standand来表示功能。 Stroustrup没有发明许多特殊类型系统的运算符重载案例,而是决定提供两种正交功能:引用,它们是语法无关的不可变指针(以及“讨论变量”的类型),以及运算符重载,它是由干净地启用的引用。

答案 1 :(得分:0)

引用是一种使两个名称别名为同一内存的方法。 以此功能为例:

void something_cpp(int &x)
{
    x = 2;
}

您可以在C语言中将其视为以下内容:

void something_c(int *x)
{
    *x = 2;
}

类似于在c ++中返回引用的函数:

int something[10];

int &something2_cpp(void)
{
    return something[0];
}

int main(int argc, char *argv[])
{
    something2_cpp() = 10;
}

在C中可以这样想:

int something[10];

int *something2_c(void)
{
    return &something[0];
}

int main(int argc, char *argv[])
{
    *something2_c() = 10;
}