可能重复:
FAQ: How to pass objects to functions in C++?
Pointer vs. Reference
大家好,
在c / c ++中,
我们可以通过引用传递一个对象或传递对象的指针
例如:
我想创建一个函数,它将字符串向量作为输入并输出一个包含每个字符串的值的映射。函数的返回值是bool,表示成功或失败。
功能(通过引用致电)
bool calculateSomeValue( vector<string> input, map<string, double>& result) { //// bla bla bla return true/false; }
功能(使用指针)
bool calculateSomeValue( vector<string> input, map<string, double>* result) { //// bla bla bla return true/false; }
哪一个最好?有没有人知道这两种选择的利弊?
提前感谢。
答案 0 :(得分:11)
这是一种风格问题。在Google(请参阅Google C++ style guidelines),以下内容将首选:
bool CalculateSomeValue(
const vector<string>& input, map<string, double>* result);
这是因为使用指针需要在调用站点显式使用&符号:
CalculateSomeValue(input, &result);
与使用引用类型调用它的方式相反:
CalculateSomeValue(input, result);
通过在修改参数的情况下强制使用&符号,可以在呼叫站点清楚地知道会发生什么。使用引用时,有必要查找每个函数的文档,以了解它是否有可能修改其输入参数。
然而,指针的使用也有其缺点。特别是,指针的使用意味着您将处理null的责任从指针被解除引用的调用者(如果该变量是指针而不仅仅是具有局部变量的表达式的地址)转移到函数。也就是说,当使用指针类型时,CalculateSomeValue
需要检查nullptr
(或者需要清楚地记录它需要在调用者中进行此检查),而使用引用类型是自我记录的并清楚地表明预期会出现非空引用。
对于这种特殊的情况,我个人强烈建议采用混合方法:
bool CalculateSomeValue(
const std::vector<std::string>& input,
Output<map<string, double>> result);
...其中Output<T>
由具有签名的函数创建:
template<typename T> Output<T> WriteTo(T& output_ref);
...以及Output<T>
重载运算符->
,*
等等。这基本上会强制调用网站显式,因为输入将通过以下方式进行变更:
CalculateSomeValue(input, WriteTo(result));
......而不是:
CalculateSomeValue(input, result);
...同时获得引用的非null语义/语法。
答案 1 :(得分:1)
如果参数不是可选的,我发现c ++很多开发人员更喜欢通过引用传递。然而,许多人喜欢仅通过指针传递视觉提示。这是从C有点故障保持的这削弱作为程序长到处理引用和指针的混合使用。
你可以假设引用不是null,但你不应该假设指针。在这种情况下,你必须引进的前提脚手架/检查,以确保有人上游不相信的说法是可选的 - 如果你的防守
我个人比较喜欢通过引用传递,并使用描述性的方法/函数/变量名(如果你只详细标签,那么人们不得不去的文档更频繁地)。这样可以使程序的意图保持清晰,并避免额外的书面检查。 get*
或update*
可能比calculate*
更明显。
使用的引用是一致的,明确定义的,并且因为你不处理用混合变量/参数类型产生更简单的方案。
它确实没有让你在这种情况下,选择一个显著区别,只是是一致在您的使用情况。我使用的另一个提示是将修改后的参数放在同一个地方。具体来说,它们先于不断的争论。
答案 2 :(得分:0)
bool calculateSomeValue( vector<string> input, map<string, double>&* result)
指向参考?这甚至都不会编译。第一个是正确的,只有正确的才是最好的!
struct A {};
void f(A & *a) {}
编译提供rrror:
prog.cpp:7:错误:无法声明 指向'struct A&amp;'
的指针
Ideone示例:http://www.ideone.com/8PJA5
答案 3 :(得分:0)
你的第二个代码示例似乎不正确,因为你试图接受一个不应该编译的引用指针。
通过引用传递并传递指针同样有效(如果我错了,有人会纠正我,但我的理解是引用本质上是一个自动创建的指针然后被无缝解除引用),但通过引用传递是建议因为它更安全:
有些人更喜欢显式指针语法,它明确指出它是传入对象的指针(因为你必须取消引用)。
答案 4 :(得分:0)
最佳解决方案不存在。它从一个案例到另一个案例。
例如,在某些情况下,接下来会更好:
map<string, double> calculateSomeValue( const vector<string> &input )
{
map<string, double> res;
// do something with input to form the output
return res;
}
但是,如果可以的话,更愿意使用标准算法
答案 5 :(得分:0)
我假设第二个应该只是按点而不是指向引用的指针。
两者之间的决定只是风格和品味的问题。两行的编译结果可能相同。
通常对于输出参数,C ++样式指南说它应该是指针。
答案 6 :(得分:0)
使用引用的唯一时间是实现需要它们的标准运算符。
然而,除此之外,指针应始终优先于任何应用方法的参考。
用户对象经常存储在指针中,智能或其他方式。当按需创建对象时,对始终有效的引用的约束太严格了。这使得参考参数不方便使用,因为需要进行笨拙的操作来传递该值。 referenceFunc( (*pObj) );
通过引用传递是试图实施合同范式的廉价替代品。哪个c ++不支持。
对该传递引用的所有(* somePtr)操作意味着你无论如何都会得到空指针调试,只是更加模糊,因为空指针看起来不像指针。
当程序员无法通过简单的检查判断某个函数的哪些参数可能会发生变化时,不要理解维护问题。