我了解指针和引用的语法和一般语义,但是我应该如何决定什么时候在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)将调用指针版本并在运行时中断),从可维护性的角度来看,在必须存在对象的地方使用引用是有意义的,尽管失去语法的清晰性是一种遗憾。
尽可能使用引用,必须使用指针。
避免指针,直到你不能。
原因是指针使事情更难跟踪/阅读,比任何其他结构更不安全,更危险的操作。
所以经验法则是只有在没有其他选择的情况下才使用指针。
例如,当函数在某些情况下可以返回nullptr时,返回指向对象的指针是一个有效的选项,并且假设它将会返回。也就是说,更好的选择是使用类似于std::optional(需要c++ 17;在此之前,有boost::optional)。
另一个例子是为特定的内存操作使用指向原始内存的指针。这应该隐藏并本地化在代码的非常狭窄的部分,以帮助限制整个代码库的危险部分。
在你的例子中,使用指针作为参数是没有意义的,因为:
如果你提供nullptr作为参数,你将进入未定义行为领域;
引用属性版本不允许(没有容易发现的技巧)1的问题。
对于用户来说,引用属性版本更容易理解:您必须提供一个有效的对象,而不是可以为空的东西。
如果函数的行为必须在有或没有给定对象的情况下工作,那么使用指针作为属性表明您可以将nullptr作为参数传递,这对函数来说是好的。这是用户和实现之间的一种契约。
以下是一些指导方针。
函数使用传递的数据而不修改它:
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。