我了解指针和引用的语法和一般语义,但是我应该如何决定什么时候在API中使用引用或指针比较合适?

当然,有些情况需要其中一个(操作符++需要引用参数),但一般来说,我发现我更喜欢使用指针(和const指针),因为语法很清楚,变量是破坏性传递的。

例如,在以下代码中:

void add_one(int& n) { n += 1; }
void add_one(int* const n) { *n += 1; }
int main() {
  int a = 0;
  add_one(a); // Not clear that a may be modified
  add_one(&a); // 'a' is clearly being passed destructively
}

使用指针,它总是(更)明显的发生了什么,所以对于api和类似的地方,清晰度是一个大问题,指针不是比引用更合适吗?这是否意味着引用应该只在必要时使用(例如操作符++)?其中一种是否存在性能问题?

编辑(过时的):

除了允许NULL值和处理原始数组之外,选择似乎还取决于个人喜好。我接受下面的答案,引用谷歌的c++风格指南,因为他们提出的观点是“引用可能会令人困惑,因为它们有值语法,但有指针语义。”

由于需要额外的工作来清除不应该为NULL的指针参数(例如,add_one(0)将调用指针版本并在运行时中断),从可维护性的角度来看,在必须存在对象的地方使用引用是有意义的,尽管失去语法的清晰性是一种遗憾。


当前回答

以下是一些指导方针。

函数使用传递的数据而不修改它:

If the data object is small, such as a built-in data type or a small structure, pass it by value. If the data object is an array, use a pointer because that’s your only choice. Make the pointer a pointer to const. If the data object is a good-sized structure, use a const pointer or a const reference to increase program efficiency.You save the time and space needed to copy a structure or a class design. Make the pointer or reference const. If the data object is a class object, use a const reference.The semantics of class design often require using a reference, which is the main reason C++ added this feature.Thus, the standard way to pass class object arguments is by reference.

函数修改调用函数中的数据:

1.如果数据对象是内置数据类型,则使用指针。如果你是现货代码 与fixit(&x)一样,其中x是int型,很明显这个函数打算修改x。

2.如果数据对象是一个数组,则使用唯一的选择:指针。

3.如果数据对象是结构,请使用引用或指针。

4.如果数据对象是类对象,则使用引用。

当然,这些只是指导方针,可能有不同的理由 选择。例如,cin使用基本类型的引用,因此您可以使用cin >> n 而不是cin >> &n。

其他回答

两者的性能完全相同,因为引用是作为指针在内部实现的。因此你不需要担心这个。

关于何时使用引用和指针,没有普遍接受的约定。在少数情况下,您必须返回或接受引用(例如,复制构造函数),但除此之外,您可以自由地按照自己的意愿进行操作。我遇到的一个相当常见的约定是,当形参必须引用现有对象时使用引用,当可以使用NULL值时使用指针。

一些编码约定(如谷歌的)规定应该总是使用指针或const引用,因为引用有一点不清楚的语法:它们有引用行为但有值语法。

以下是一些指导方针。

函数使用传递的数据而不修改它:

If the data object is small, such as a built-in data type or a small structure, pass it by value. If the data object is an array, use a pointer because that’s your only choice. Make the pointer a pointer to const. If the data object is a good-sized structure, use a const pointer or a const reference to increase program efficiency.You save the time and space needed to copy a structure or a class design. Make the pointer or reference const. If the data object is a class object, use a const reference.The semantics of class design often require using a reference, which is the main reason C++ added this feature.Thus, the standard way to pass class object arguments is by reference.

函数修改调用函数中的数据:

1.如果数据对象是内置数据类型,则使用指针。如果你是现货代码 与fixit(&x)一样,其中x是int型,很明显这个函数打算修改x。

2.如果数据对象是一个数组,则使用唯一的选择:指针。

3.如果数据对象是结构,请使用引用或指针。

4.如果数据对象是类对象,则使用引用。

当然,这些只是指导方针,可能有不同的理由 选择。例如,cin使用基本类型的引用,因此您可以使用cin >> n 而不是cin >> &n。

把我的一角硬币放进去。我刚做了个测试。一个打喷嚏的人。我只是让g++使用指针而不是引用来创建同一个小程序的程序集文件。 当查看输出时,它们是完全相同的。除了符号命名。所以看性能(在一个简单的例子中)没有问题。

现在谈谈指针与引用的话题。恕我直言,我认为清晰是最重要的。一旦我读到内隐行为,我的脚趾就开始卷曲。我同意引用不能为NULL是很好的隐式行为。

解引用NULL指针不是问题所在。它将使您的应用程序崩溃,并且易于调试。一个更大的问题是未初始化的指针包含无效值。这很可能导致内存损坏,导致没有明确起源的未定义行为。

这就是我认为引用比指针安全得多的地方。我同意前面的说法,接口(应该清楚地记录,参见合同设计,Bertrand Meyer)定义了函数参数的结果。考虑到这些因素,我的偏好是 尽可能使用引用。

正确编写的示例应该如下所示

void add_one(int& n) { n += 1; }
void add_one(int* const n)
{
  if (n)
    *n += 1;
}

这就是为什么推荐信在可能的情况下更可取 ...

在我的实践中,我个人确定了一个简单的规则——对可复制/可移动的原语和值使用引用,对具有长生命周期的对象使用指针。

对于Node的例子,我肯定会使用

AddChild(Node* pNode);