我了解指针和引用的语法和一般语义,但是我应该如何决定什么时候在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)将调用指针版本并在运行时中断),从可维护性的角度来看,在必须存在对象的地方使用引用是有意义的,尽管失去语法的清晰性是一种遗憾。


当前回答

我的经验法则是:

Use pointers for outgoing or in/out parameters. So it can be seen that the value is going to be changed. (You must use &) Use pointers if NULL parameter is acceptable value. (Make sure it's const if it's an incoming parameter) Use references for incoming parameter if it cannot be NULL and is not a primitive type (const T&). Use pointers or smart pointers when returning a newly created object. Use pointers or smart pointers as struct or class members instead of references. Use references for aliasing (eg. int &current = someArray[i])

无论您使用哪一种,如果参数不明显,请不要忘记记录函数及其参数的含义。

其他回答

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

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

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

以下是一些指导方针。

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

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。

复制自wiki-

A consequence of this is that in many implementations, operating on a variable with automatic or static lifetime through a reference, although syntactically similar to accessing it directly, can involve hidden dereference operations that are costly. References are a syntactically controversial feature of C++ because they obscure an identifier's level of indirection; that is, unlike C code where pointers usually stand out syntactically, in a large block of C++ code it may not be immediately obvious if the object being accessed is defined as a local or global variable or whether it is a reference (implicit pointer) to some other location, especially if the code mixes references and pointers. This aspect can make poorly written C++ code harder to read and debug (see Aliasing).

我完全同意这一点,这就是为什么我认为只有在你有充分理由的时候才应该使用推荐信。

从 C++ 常见问题精简版 -

Use references when you can, and pointers when you have to. References are usually preferred over pointers whenever you don't need "reseating". This usually means that references are most useful in a class's public interface. References typically appear on the skin of an object, and pointers on the inside. The exception to the above is where a function's parameter or return value needs a "sentinel" reference — a reference that does not refer to an object. This is usually best done by returning/taking a pointer, and giving the NULL pointer this special significance (references must always alias objects, not a dereferenced NULL pointer). Note: Old line C programmers sometimes don't like references since they provide reference semantics that isn't explicit in the caller's code. After some C++ experience, however, one quickly realizes this is a form of information hiding, which is an asset rather than a liability. E.g., programmers should write code in the language of the problem rather than the language of the machine.

这不是品味的问题。以下是一些明确的规则。

如果你想在声明变量的范围内引用静态声明的变量,那么使用c++引用,这将是完全安全的。这同样适用于静态声明的智能指针。通过引用传递参数就是一个例子。

如果你想从一个比它声明的范围更宽的范围中引用任何东西,那么你应该使用一个引用计数智能指针,以确保它的完全安全。

为了语法方便,您可以使用引用引用集合的元素,但这并不安全;元素可以在任何时候被删除。

为了安全地保存对集合元素的引用,必须使用引用计数智能指针。