我可以想象一种情况,其中输入参数可以为NULL,因此传递指针是首选但不是传递引用?
任何人都可以添加更多案例吗?
答案 0 :(得分:39)
在传递的对象实际上将被修改的情况下,有些像pass-by-pointer更好。当对象通过引用传递时,它们使用pass-by-const-reference来避免对象的副本,但不会在函数中更改。
在插图中,请执行以下功能:
int foo(int x);
int foo1(int &x);
int foo2(int *x);
现在在代码中,我执行以下操作:
int testInt = 0;
foo(testInt); // can't modify testInt
foo1(testInt); // can modify testInt
foo2(&testInt); // can modify testInt
在调用foo vs foo1时,从调用者角度(或读取代码的程序员)来看,该函数可以修改testInt而不必查看函数的签名。查看foo2,读者可以很容易地看到该函数实际上可能会修改testInt的值,因为该函数正在接收参数的地址。请注意,这并不能保证对象实际被修改,但是在使用引用和指针时保持一致有帮助。通常,如果要始终如一地遵循此准则,则应始终在要避免复制时传递const引用,并在希望能够修改对象时传递指针。
答案 1 :(得分:20)
C++ FAQ对这个问题有一个非常好的答案:
尽可能使用参考,和 必要的指针。
参考文献通常优先于 任何你不需要的指针 “重新安装”。这通常意味着 引用在a中最有用 class的公共接口。参考 通常出现在皮肤上 对象和内部的指针。
以上例外是a 函数的参数或返回值 需要一个“哨兵”参考 - a 不参考的参考文献 宾语。这通常最好通过 返回/拿指针,给予 NULL指针这个特殊 意义(引用应始终 别名对象,而不是取消引用的NULL 指针)。
注意:老C线程序员有时候 因为他们不喜欢参考 提供不是的参考语义 在调用者的代码中显式。后 但是,有一些C ++经验 很快意识到这是一种形式 信息隐藏,这是一种资产 而不是责任。例如。, 程序员应该编写代码 问题的语言而不是 机器的语言。
答案 2 :(得分:6)
在现实世界编程中有许多情况,其中参数不存在或无效,这可能取决于代码的运行时语义。在这种情况下,您可以使用NULL(0)来表示此状态。除此之外,
虽然如果花费足够的时间来正确设计代码,可以避免这些情况;在实践中,每次都不可能。
答案 3 :(得分:4)
除了关于所有权语义的其他一些答案(特别是工厂函数)。
虽然不是技术原因,但常见的样式指南要求是任何可以修改的参数都应该通过指针传递。这使得在调用现场很明显可以修改对象。
void Operate(const int &input_arg, int *output_arg) {
*output_arg = input_arg + 1;
}
int main() {
int input_arg = 5;
int output_arg;
Foo(input_arg, &output_arg); // Passing address, will be modified!
}
答案 4 :(得分:4)
规则编号为1:如果NULL是函数上下文中函数参数的有效值,则将其作为指针传递,否则将其作为参考传递。
基本原理,如果它不能(不应该!)永远为NULL,那么不要因为它是NULL而不必检查NULL或冒问题。
答案 5 :(得分:1)
在处理原始内存时(例如,如果创建自己的内存池),您需要使用指针。但是你是对的,在普通代码中,指针的唯一用途是可选参数。
答案 6 :(得分:1)
在C ++中,在大多数情况下几乎不需要通过指针。您应该首先考虑替代方案:模板,(const)引用,容器,字符串和智能指针。也就是说,如果你必须支持遗留代码,那么你需要使用指针。如果您的编译器是简约的(例如,嵌入式系统),您将需要指针。如果你需要与一个C库(一个你正在使用的非常特殊的驱动程序的某种类型的系统库)交谈,那么你需要使用指针。如果你想处理非常特殊的内存偏移,那么你需要指针。
在C指针中是一流的公民,他们在考虑消除它们时过于根本。
答案 7 :(得分:1)
随时传递函数指针。 或者如果你有一个“重置”方法a la auto_ptr。
答案 8 :(得分:1)
当您需要操作(例如调整大小,重新分配等)函数内指针指向的地址时,您需要一个指针。
例如:
void f( int* p )
{
// ..
delete []p;
p = new int[ size ];
//...
}
与引用不同,指针的值可以更改和操作。
答案 9 :(得分:1)
这不是特定的参数传递,但确实会影响参数传递。
您可以拥有指针的容器/聚合,但不能包含引用。虽然引用是多态的,但只有指针支持“更新”操作,这对于容器使用是必不可少的(特别是因为你还不能大量初始化引用,不确定C ++ 0x聚合初始化器是否会改变它)。
因此,如果你有一个装满指针的容器,你通常最终会使用接受指针而不是引用的函数来管理它。
答案 10 :(得分:0)
可以想象,可以编写一个函数来对内存执行某些操作,例如重新分配它以使其更大(返回新指针)。
答案 11 :(得分:0)
如果我需要传递一个对象数组,我需要通过指针传递。数组并不总是存储在std::vector<>
。
除此之外,传递指针允许NULL并且通过引用传递不会,因此我将这种区别用作SQL中的NULL
与NOT NULL
列的契约,并且松散地像“函数返回bool
:true
=成功且false
=失败,而函数返回int
:返回值是结果代码,其中0
=成功和其他是失败“。
答案 12 :(得分:0)
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments