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


当前回答

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

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

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

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

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

其他回答

要记住的要点:

指针可以为NULL,引用不能为NULL。 引用更容易使用,当我们不想改变值而只是需要在函数中引用时,const可以用作引用。 与*一起使用的指针,与&一起使用的引用。 当需要指针算术运算时使用指针。 你可以有指向void类型int a=5的指针;Void *p = &a;但不能有对void类型的引用。

指针Vs参考

void fun(int *a)
{
    cout<<a<<'\n'; // address of a = 0x7fff79f83eac
    cout<<*a<<'\n'; // value at a = 5
    cout<<a+1<<'\n'; // address of a increment by 4 bytes(int) = 0x7fff79f83eb0
    cout<<*(a+1)<<'\n'; // value here is by default = 0
}
void fun(int &a)
{
    cout<<a<<'\n'; // reference of original a passed a = 5
}
int a=5;
fun(&a);
fun(a);

判断什么时候用什么

指针:用于数组、链表、树实现和指针算术。

在函数参数和返回类型中。

以下是一些指导方针。

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

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。

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

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

AddChild(Node* pNode);

对于指针,您需要它们指向某个对象,因此指针需要占用内存空间。

例如,接受整数指针的函数将不接受整数变量。因此,您需要首先为它创建一个指针,以便传递给函数。

作为参考,它不会占用内存。你有一个整数变量,你可以把它作为引用变量传递。就是这样。您不需要专门为它创建引用变量。

我的经验法则是:

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])

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