当传递指针是首选的C ++传递引用?
我可以想象一个情况,其中input参数可以是NULL,以便通过指针是首选,但不是通过引用传递?
任何人都可以添加更多的案件?
有些像传递对象实际上将被修改的情况下更好。 当通过引用传递对象时,它们使用传递const引用来避免对象的副本,但不会在函数中进行更改。
在说明中,采取以下function:
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时,从调用者的angular度(或者读取代码的程序员)并不清楚该函数可以修改testInt而不必查看函数的签名。 看foo2,读者可以很容易地看到该函数实际上可能会修改testInt的值,因为函数正在接收参数的地址。 请注意,这并不能保证对象实际上是被修改的,但这就是在使用引用和指针帮助时一致的地方。 一般来说,如果你想一直遵循这个指导原则,你应该总是在你想避免副本的时候传递const引用,并且当你想要修改这个对象的时候通过指针传递。
C ++ FAQ对这个问题有一个非常好的答案:
尽可能使用参考,必要时使用指示。
只要不需要“重新设置”,引用通常优先于指针。 这通常意味着引用在类的公共接口中是最有用的。 引用通常出现在对象的皮肤上,指向内部的指针。
上述例外是函数的参数或返回值需要一个“哨兵”引用 – 一个引用,不引用一个对象。 这通常最好通过返回/获取一个指针来完成,并给予NULL指针这个特殊的意义(引用应该总是别名对象,而不是一个取消引用的空指针)。
注意:旧的C语言程序员有时不喜欢引用,因为他们提供的引用语义在调用者的代码中并不明确。 然而,经过一些C ++经验之后,人们很快意识到这是一种信息隐藏,这是一种资产而不是责任。 例如,程序员应该用问题的语言来编写代码,而不是使用机器的语言。
在现实世界编程中有很多情况,其中一个参数不存在或者是无效的,这可能取决于代码的运行时语义。 在这种情况下,你可以使用NULL(0)来表示这个状态。 除此之外,
- 指针可以重新分配给一个新的状态。 一个参考不能。 在某些情况下这是可取的。
- 一个指针可以帮助传输所有权语义。 如果参数状态用于在单独的线程中执行,并且在线程退出之前通常不进行轮询,则这在multithreading环境中特别有用。
尽pipe如果花费足够的时间来适当地devise代码,可以避免这些情况; 在实践中,每一次都是不可能的。
除了关于所有权语义(特别是工厂职能)的一些其他答案。
虽然不是一个技术原因,但一个共同的风格指导要求是,任何可能被修改的参数都应该通过指针来传递。 这使得在调用点明显可以修改该对象。
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! }
规则1:如果函数的上下文中的函数参数为NULL,则将其作为指针传递,否则将其作为参考传递。
基本原理,如果它不能(不应该!)永远是NULL,那么不要因为NULL而检查NULL或者冒险出现问题。
处理原始内存(例如,如果创build自己的内存池),你会想要使用一个指针。 但是你是对的,在普通的代码中,指针的唯一用途是一个可选参数。
在C ++中,在大多数情况下几乎不需要传递指针。 您应该首先考虑替代方法:模板,(常量)引用,容器,string和智能指针。 也就是说,如果你必须支持遗留代码,那么你需要使用指针。 如果你的编译器是简约的(例如embedded式系统),你将需要指针。 如果你需要和一个C库(一个你正在使用的非常特殊的驱动程序的系统库)交谈,那么你需要使用指针。 如果你想处理非常特殊的内存偏移,那么你将需要指针。
在C指针是一stream的公民,他们太重要了,不考虑消除它们。
任何时候你传递一个函数指针。 或者如果你有一个“重置”方法一个auto_ptr。
这并不是特定的parameter passing,但它确实会影响parameter passing。
你可以有一个容器/指针集合,但不是引用。 尽pipe引用是多态的,但只有指针支持对于容器使用至关重要的“更新”操作(尤其是因为你还不能初始化引用,不知道C ++ 0x聚合初始化器是否会改变这种情况)。
所以如果你有一个装满指针的容器,你通常最终会用接受指针而不是引用的函数来pipe理它。
当你需要操作(例如resize,重新分配等)函数内指针指向的地址时,你需要一个指针。
例如:
void f( int* p ) { // .. delete []p; p = new int[ size ]; //... }
与引用不同,指针的值可以被改变和操纵。
可以想象,一个函数可以写成对内存做某些事情,例如重新分配它以使其变大(返回新的指针)。
如果我需要传递一个对象数组,我需要传递指针。 数组并不总是存储在std::vector<>
。
除此之外,通过指针传递允许NULL和通过引用不传递,所以我使用这种差异作为一个合同,就像SQL中的NULL
和NOT NULL
列一样,松散地像“函数返回bool
: true
=成功和false
=失败,与函数返回int
:返回值是一个结果代码,其中0
=成功和其他失败“。
谷歌似乎对此有强烈的意见,我倾向于同意:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments