【问题标题】:Inconsistency in passing by reference - how does this simple example of passing by reference work?引用传递的不一致 - 这个简单的引用传递示例如何工作?
【发布时间】:2014-03-30 01:02:48
【问题描述】:

我有一个简单的问题,希望通过引用传递背后的基本逻辑。

这是一个代码(我们称之为 Code1):

void fn(int& a)
{
    a = 6;
}

int main()
{
    int b = 5;
    fn(b);
    cout << b;
}

这是另一个代码(Code2):

void fn(int* ptr)
{
    *ptr = 6;
}

int main()
{
    int b = 5;
    fn(&b);
    cout << b;
}

还有一个按值传递代码(代码 3):

void fn(int a)
{
    a = 6;
}

int main()
{
    int b = 5;
    fn(b);
    cout << b;
}

这是我的问题。直观地说,我看到,在通过值(代码 3)传递时,值被复制,即 a 只会将 b 的值取/复制到自身中。因此,作为一般规则,我看到传递的值总是被复制到被调用的函数(这里是 fn)。即使有指针代码(即Code2),代码2的第一行确保int *ptr = &amp;a;

我不明白这在 Code1 中是如何工作的。说&amp;a = b 毫无意义。这是一个例外,还是符合与上段讨论的案例一致的规则?

谢谢!

【问题讨论】:

    标签: c++ function parameter-passing


    【解决方案1】:

    在这个函数中:

    void fn(int &a) {
    a=6;
    }
    

    术语“&a”并不意味着“变量a的地址”。它的意思是“一个名为a 的引用”。代码 1 和代码 2 实际上是相同的(但请注意,代码 2 中的函数可以传递一个无效指针,这对于代码 1(几乎)是不可能的)。

    【讨论】:

    • "这对于代码 1 来说(几乎)是不可能的" 这主要是语义上的区别。所有编译器都将引用实现为下面的指针,如果你有像void fn2(int *a){ fn(*a); } 这样的函数,它将编译这个函数,因为它只是简单地传递地址,而不是“取消引用”。所以有效地你可以传递一个无效的引用,就像传递一个无效的指针一样容易。语言纯粹主义者会说无效指针上的取消引用表达式是未定义的行为,因此之后的任何内容都毫无意义。但这只是学术上的技术问题,程序员看不到。
    【解决方案2】:

    对于大多数意图和目的,引用只是变相的指针。不同的语法,相同的效果(大部分)。

    【讨论】:

    • 你想要引用的唯一原因是 a) 指针通常过于笼统和强大 b) 我们喜欢语法糖。让编译器摆脱理解指针的沉重负担。
    • @Deduplicator 我从来没有买过参数 a。它使指针看起来像黑魔法,不鼓励学习它们。
    • 如果您实际上不需要对指针本身执行算术运算,它消除了一个概念级别的间接。大约 4-5 星,你应该为此感到庆幸......否则,它肯定只是为了糖。
    • @Deduplicator 您可能希望在不同的时间指向不同的对象。
    • @Deduplicator 你说,如果你不需要执行指针运算,那只是为了糖。但是如果你想用相同的指针指向不同的对象,你也需要一个指针。无法重新安装参考。
    【解决方案3】:

    从概念上讲,在您的第一种情况下,发生的情况是同一个变量有两个标签:b,在main() 范围内可见;和a,在fn范围内可见。

    您不必担心编译器在“幕后”做了什么来实现这个概念。

    如果您在精神上将编译器的“幕后”操作提升为实际想象中的 C++ 原则,例如“引用是变相的指针”,那么它会让你对一个实际上非常简单的概念感到困惑:为变量赋予多个名称的能力。

    作为函数参数没什么特别的;例如你可以写main():

    int a;
    int &c = a;
    

    完全等价于:

    int c;
    int &a = c;
    

    在这两种情况下,都有一个带有两个标签 acint 变量。

    【讨论】:

      猜你喜欢
      • 2012-07-11
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      相关资源
      最近更新 更多