【问题标题】:C and C++ pass by pointer and pass by reference confusionC和C++指针传递和引用传递混淆
【发布时间】:2021-11-12 19:18:16
【问题描述】:

所以我了解如何将地址传递给 C 函数以避免传递值。但我不明白的是在 C++ 中通过引用传递。我对 C 缺乏理解,如果你通过引用传递变量,你只会得到一个基于地址的废话 int 值。比如你做了:

int x = 5;
int* p = x;
int y = p;

y 将是一个无意义的 int 值。所以我不明白基于上述逻辑的C++引用传递。是否有一些编译器标识您正在尝试执行的操作,以便以使其等效于 C 代码的方式对其进行编译?有关 C 和 C++ 的指针传递和引用传递,请参见下文:

// C pass by pointer value
void main() {
    int a = 1;
    int b = 2;

    swap(&a, &b);
    }

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

// C++ pass by reference
void main() {
    int a = 1;
    int b = 2;

    swap(a, b);
    }

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

【问题讨论】:

  • C++ 引用只是指针的抽象。无论您使用的是引用还是指针,C++ 编译器都可能生成相同的代码。
  • 不一定是这样。如果编译器可以内联解析名称,那么它可以简单地在其符号查找表中具有相同值的两个名称。
  • 如何实现指针和引用并没有被标准指定。这完全取决于您使用的实现(即编译器、cpu 等)。我的猜测是,在大多数情况下,它们的实现方式相同。见godbolt.org/z/5Ws8zYcsY
  • "我缺乏理解来自 C,如果你通过引用传递变量,你只会得到一个基于地址的废话 int 值" - C 没有t 根本没有引用,只有指针。 C++ 有引用。
  • 在 C 中引用引用并没有错。通过取消引用指针获得引用。 C 没有命名直接引用。

标签: c++ c pointers reference


【解决方案1】:

你在问一个引发圣战的问题。

对象

对象是某种事物的一个实例:它有自己的内存和一切。我们代码中的很多对象都有名称

int number_of_birds_in_hand = 0;
std::string users_name = "Fred";

您会看到模式:类型、名称、值。

名称是对象的直接引用,或别名

指针

指针是对对象的间接引用。它们是间接的,因为它们本身就是对象,具有自己的名称和值:

const char * filename = "hello.txt";

我们倾向于混淆它,因为它看起来filename 的值 "hello.txt",但事实并非如此。 filename 的值是文本的地址。我们可以随时更改该地址:

filename = "goodbye.txt";

(就像 C 和 C++ 中的任何变量一样,我们可以告诉编译器不要让我们这样做,使用:const char * const filename。)

我们取消引用一个指针来获得对对象的直接引用。直接引用没有名称,但它解析为具有该对象的名称。

int x = 12;
int * y = &x;
*y = -7;

构造*y 解析为对x 的直接引用(或别名):访问*y 与访问x 相同。但是y本身只是对自己对象值的引用。

参考文献

C++ 添加了一个新结构,称为reference。从语言的角度来看,这正是它的本质:对象的另一个名称。

int x = 12;
int & y = x;
y = -7;

这里,xy 都是同一个对象的别名(或直接引用)!

圣战

我们谈论这些事情的方式让人们前进。 C++ 标准有一种方法可以做到这一点。 CS 文学自始至终都有另一个。非常聪明、知识渊博的人可能对这个话题有不同的看法。

我个人在使用 C 语言时将指针称为引用没有问题。但在 C++ 中,这种语言会与真正的引用(而不是指针的间接引用)混淆。

人们喜欢的一个常见论点是引用是否真的是指针。答案是视情况而定。有时是,有时不是。

这是一个幼稚的论点,因为从 C++ 语言提供的角度来看它们是不同的东西。它们在底层的工作方式真的只对制作编译器的人很重要。

然后你也有整个 pass-by-pointer 圣战......但最好把那个留给另一个 SO 问题。

最后的想法

诀窍是理解人们在提及这些事物时的意思,如果您不确定,请询问。如果有人对你提到它的方式感到愤怒和愤怒,试着使用他们使用的术语。他们可以在没有你的情况下生小母牛。

在普通 C++ 中,您有对象值、指针和引用,并且根据您的要求,它们永远不会被混淆。如果你不确定,就说你传递了一个指向函数的指针,这样你就可以取消引用它来获得目标值,呵呵。

【讨论】:

  • 感谢您的深入回复!所以 C++ 添加了引用作为一个新的结构。
  • 嗯.... new 是相对的,它们长期以来一直是语言的一部分。我只是认为有太多的书仍然在教“旧”风格的 C++,其中只使用指针。
  • “新”在某种意义上说 C++ 有它而 C 没有。这是一个旧的新的......我猜...... :-D 可悲的是,书籍问题永远不会消失。即便如此,这里也有自己的 C 和 C++ 书籍问题……
  • C/C++ 通常被称为“高级汇编程序”,因为它们是围绕硬件设计的。这个答案表明,C++ 也是一种面向编译器的语言,也就是说,它有许多特性,只有对编译器的工作原理有所了解,才能完全理解。另一个例子是移动语义和奇怪的“内联”关键字。这种“面向编译器”是间接的,因为它从不强制特定的编译器技术,只是使它们成为可能。就像指向成员的指针(与标准指针非常不同)或虚函数(它们与虚表一起使用吗?)。
  • 我认为它根本没有这么说。引用是一种高级语言功能,一直以某种形式存在于各种语言中。问题在于人们的想法:他们忙于尝试自行设计 C 和 C++ 的内部工作原理,以至于没有考虑到它们是在虚拟机上设计的,就像 Pascal、Java 或 BF 一样。虽然虚拟机确实可以很好地与当前的硬件配合使用,但出于某种原因,人们不能只接受语言所呈现的世界,而是试图通过向后查看来强制它......
猜你喜欢
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 2013-04-03
  • 2016-05-02
  • 1970-01-01
  • 2010-12-07
  • 2013-12-24
  • 2013-01-13
相关资源
最近更新 更多