【问题标题】:pointers vs. references vs. a regular pass by value c++指针 vs. 引用 vs. 常规值传递 c++
【发布时间】:2011-01-19 11:38:05
【问题描述】:

请在回答之前阅读。我不想让你为我陈述显而易见的事情。谢谢:D

我试图区分指针和按值传递。而且我想我理解它们,但是我正在阅读的来源不清楚的一件事是传递指针和按值传递之间的区别。考虑以下...

andy = 25;
fred = andy;
ted = &andy; 

第一行将值 25 传递给 andy。第二行将andy 的值传递给fred。现在 fred 拥有值 25。第三行传递对 ted 的引用。现在ted保存了andy的内存地址,其中保存了25的值。现在看下一段代码

andy = 25;
fred = andy;
ted = &andy; 
joe = *andy;

上面的代码看起来就像第一个sn-p,只是我们将andy的指针传递给了joe。现在 joe 拥有 25 的指针值。这几乎与刚刚执行 (joe = andy) 相同。没有*

传递指针值与只传递值有什么区别???

在我的解释中,如果后来我决定更改 andy/ 的值,与我只是按值传递相比,joe 的指针值似乎仍然受到影响,它不会受到影响。 T

据我所知,通过引用传递和通过指针传递之间的唯一区别是一个保存地址,另一个保存该地址内的值。如果任何持有该值引用的变量决定更改它,它仍然可以更改。如果是这样的话,按引用传递和按值传递又有什么意义。

这是我正在阅读的链接

http://www.cplusplus.com/doc/tutorial/pointers/

谢谢大家!!!

【问题讨论】:

  • 按值/引用传递不同于赋值。
  • 这个问题不输入变量是没有意义的。没有打字,您无法分辨 & 的含义。你也没有“传递”任何东西。
  • 我刚刚发送了一个指向我所指内容的链接。如果您不明白我在说什么,那么链接可能会更好地解释它。而且我认为您至少应该让我在回答我的问题之前详细说明一下。毕竟我是在寻求帮助和 C++ 的新手。

标签: c visual-studio visual-c++ visual-studio-2008


【解决方案1】:

您所说的与传递引用或传递值无关。这些术语仅指进行函数调用时参数发生的情况。典型的例子是swap() 函数。这个函数:

void swap(int a, int b)
{
    int t = a;
    a = b;
    b = tmp;
}

什么都不做;如果您调用它,参数将不会被交换,因为它们是按值传递的。如果你让它们按引用传递(在 C++ 中)或者你传递指针(在 C 或 C++ 中),它会做你想做的事:

void swap(int *a, int *b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

或仅在 C++ 中,

void swap(int &a, int &b)
{
    int t = a;
    a = b;
    b = a;
}

按引用传递版本的优点是可以保证获得良好的引用。第一个例子,如果你传递了错误的指针,你的程序会崩溃。

【讨论】:

【解决方案2】:

你不能这样做 joe = *andy 因为 andy 不是指针,它是一个 int。

但是,您可以使用joe = *ted,因为 ted 是一个指针。

假设你这样做了:

andy = 25; 
fred = andy; 
ted = &andy;  
joe = *ted;
andy = 26;
jim = *ted;

那么 joe 的值为 25,而 jim 的值为 26。

这样做的原因是 ted 是一个指向 andy 的指针。使用 *ted 会在那个时候为您提供该指针的值。

【讨论】:

  • 我想我现在明白了。所以任何时候你通过值传递一个指针,你不一定是通过值传递,而是通过引用传递。按值传递引用的唯一方法。是使用 *. ??
  • 如果您使用术语“分配”而不是“通过”可能会更清楚,因为通过通常用于为函数提供值,这就是您收到关于此的响应的原因。所以是的,获取存储在指针上的实际值的方法是使用 * 取消引用它 - 然后您可以将该值分配给变量。当你使用 &andy 得到 andy 的地址,然后将它分配给 ted 时,你实际上是在将 'pointer to andy' 分配给 ted。
  • 大声笑,好吧,这就解释了为什么每个人都给我这些奇怪的反应。谢谢!
【解决方案3】:

我想你就在那里,但你混淆了术语。让我们再看看你的例子:

安迪 = 25;
弗雷德 = 安迪;
ted = &andy;

第一行将值 25 分配给 andy。 第二行将 andy 持有的值分配给 fred(在本例中为 25)。 第三行将andy的地址分配给ted。

所有三个变量都有独立的值。更改其中任何一个都不会影响其他。

现在,看看你的下一个例子:

安迪 = 25;
弗雷德 = 安迪;
泰德 = &andy;
乔=*安迪;

就像你说的,前三行是一样的。第四行将 andy 指向的值赋给 joe。在这种情况下,joe 现在会将值保存在内存位置 25,因为 andy 被视为内存位置(在这种情况下,实际值是未知的,因为我们不知道从数据中存储在地址 25 的内容)。

同样,此时所有四个变量都保持独立值。改变其中任何一个都不会影响其他的价值。

让我们看另一个例子:

安迪 = 35;
吉姆 = &andy; 亚历克斯 = *吉姆;

第一行将值 25 分配给 andy。这里没有什么新鲜事。 第二行将andy 的地址分配给jim。 第三行取消引用存储在 jim 中的地址并将值分配给 alex。变量 alex 现在保存的值是 25。但是,alex 保存的 25 与 alan 保存的 25 不同,因为 alan 和 alex 位于不同的内存地址。如果我们把 alan 的值改为 30,alex 仍然是 25。

最后一个例子:

安迪 = 25;
吉姆 = &andy;
*吉姆=30;

前两行和前面的例子一样,andy 的值为 25,jim 包含 andy 的地址。

第三行给jim指向的内存地址赋值30。由于这与 andy 所在的地址相同,因此 andy 现在的值是 30。在这种情况下,andy 和 *jim 引用相同的内存位置。

术语传递值和传递指针(或传递引用)是指将参数传递给函数。传值时,如:

void myfunc(int a) { a = a+5; }

然后调用如下:

int b=2;
我的函数(b);

从函数返回时 b 的值不会改变,因为您只是将 b 的值传递给函数,将其分配给 a。变量 a 已更改,但由于它位于不同的内存地址,因此更改 a 不会影响 b 的值。

但是当按指针传递时,如:

void myfunc(int* a) { *a = *a+5; }

然后调用如下:

int b=2;
myfunc(&b);

b 的值从 2 更改为 7,因为您将 b 的地址传递给函数,然后取消引用该地址以获取它的当前值,添加 5,并将结果存储回相同的地址。当函数返回时,存储在b地址的值已经更新。

【讨论】:

  • 是的,我现在明白了。我很欣赏你的回应,我肯定对它有更好的把握。
【解决方案4】:

您的示例显示了赋值和引用/取消引用指针/对象的示例,而不是按值或引用传递。就像上面撒克逊人所说的,你不能分配 joe=*andy。

简单来说,您可以将它们定义为:

  • 按值传递:你传递一个副本 函数的值。副本 存在的范围内 功能而已。对它的任何更改都是 范围的本地,例如。无效函数(int 一)
  • 通过引用传递:您将保存值的对象的地址传递给函数,并且该对象仍然存在于其父范围内。您拥有父范围内的对象的地址,因此将对同一对象进行更改。例如。 void funA(int& a)
  • 通过指针传递:您传递一个指针来保存该对象的地址。您实际上是将指针作为值(保存对象的地址)传递给方法。如果将指针更改为指向另一个对象,则父作用域中的原始对象不会更改。如果你想改变它指向的对象,那么你必须尊重它。例如。 void funA(int* a)

【讨论】:

    【解决方案5】:

    引用传递和值传递的意义是什么?

    你是对的,在这种情况下没有区别

    (a) 直接赋值,例如 (joe = andy) 和
    (b) 复制内存地址,然后取消引用,例如 (ted = &andy; joe = *ted;)

    没有区别,因为它们具有相同的作用域,即它们在同一个函数中。仅当您开始将指针传递给其他函数时,传递指针的重要性才会发挥作用。

    当我试图理解指针时(就在 6 个月前),对我来说主要的尤里卡时刻是(没有人告诉过你这个)......在 C 中,函数通过复制它们来传递它们的参数。这很重要,因为这意味着如果您只是将变量传递给其他函数,对这些变量的更改不会反映在程序中的其他函数中。

    假设您有一个跟踪班级学生人数的程序。当有新学生加入班级时,会调用 AddStudent 函数来增加班级中的学生人数。这里有 2 个版本的 AddStudent,按引用传递和按值传递。我们将从 main 中调用每一个,然后 printf 来查看结果。

    int AddStudent_pass_by_value(int value)
    {
        value = value+1;
        printf("Number of students (within function): %d\n", value);
        return 0;
    }
    
    int AddStudent_pass_by_reference(int* value)
    {
        *value = *value+1;
        printf("Number of students (within function): %d\n", *value);
        return 0;
    }
    
    int main()
    {
        int NumStudents = 0;  //number of students
        printf("Number of students, (within main): %d\n", NumStudents);
        printf("Pass it by value\n");
        AddStudent_pass_by_value(NumStudents);
        printf("Number of students (within main): %d\n\n", NumStudents); 
        /*In main, the value is still 0! The function has not changed the original variable, just a copy of it.*/
    
        printf("Now pass it by reference\n");
        AddStudent_pass_by_reference(&NumStudents);
        printf("Number of students (within main): %d\n", NumStudents);  
        /*Now, because we passed by reference, the original variable has been changed. */
        return 0;
    }
    

    希望这会有所帮助...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-10
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 2020-04-28
      • 2020-01-17
      相关资源
      最近更新 更多