C++ 函数:与号与星号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/670101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:36:59  来源:igfitidea点击:

C++ functions: ampersand vs asterisk

c++functionpointers

提问by mpen

Let's say you have a function that modifies a variable.

假设您有一个修改变量的函数。

Should you write it like this: void myfunc(int *a)or like this void myfunc(int &a)?

你应该这样写:void myfunc(int *a)还是这样void myfunc(int &a)

The former forces you to call the function with myfunc(&b)so the caller is aware that bwill be modified, but the latter is shorter and can be called simply with myfunc(b). So which is better to use? Is there something else I'm missing?

前者强制您使用 with 调用函数,myfunc(&b)以便调用者知道b将被修改,但后者更短,可以简单地使用myfunc(b). 那么哪个更好用呢?还有什么我想念的吗?

回答by Andrew Edgecombe

Pointers (ie. the '*') should be used where the passing "NULL" is meaningful. For example, you might use a NULL to represent that a particular object needs to be created, or that a particular action doesn't need to be taken. Or if it ever needs to be called from non-C++ code. (eg. for use in shared libraries)

在传递“NULL”有意义的地方应该使用指针(即'*')。例如,您可以使用 NULL 来表示需要创建特定对象,或者不需要执行特定操作。或者如果它需要从非 C++ 代码中调用。(例如,用于共享库)

eg. The libc function time_t time (time_t *result);

例如。libc 函数time_t time (time_t *result);

If resultis not NULL, the current time will be stored. But if resultis NULL, then no action is taken.

如果result不为NULL,则存储当前时间。但如果result是 NULL,则不采取任何行动。

If the function that you're writing doesn't need to use NULL as a meaningful value then using references (ie. the '&') will probably be less confusing - assuming that is the convention that your project uses.

如果您正在编写的函数不需要使用 NULL 作为有意义的值,那么使用引用(即“&”)可能不会那么混乱 - 假设这是您的项目使用的约定。

回答by JaredPar

Whenever possible I use references over pointers. The reason for this is that it's a lot harder to screw up a reference than a pointer. People can always pass NULL to a pointer value but there is no such equivalent to a reference.

只要有可能,我就使用引用而不是指针。这样做的原因是搞砸引用比搞砸指针要困难得多。人们总是可以将 NULL 传递给指针值,但没有这样的等价于引用。

The only real downside is there reference parameters in C++ have a lack of call site documentation. Some people believe that makes it harder to understand code (and I agree to an extent). I usually define the following in my code and use it for fake call site documentation

唯一真正的缺点是 C++ 中的参考参数缺乏调用站点文档。有些人认为这会使理解代码变得更加困难(我在一定程度上同意)。我通常在我的代码中定义以下内容并将其用于伪造的呼叫站点文档

#define byref
...
someFunc(byref x);

This of course doesn't enforce call site documentation. It just provides a very lame way of documenting it. I did some experimentation with a template which enforces call site documentation. This is more for fun than for actual production code though.

这当然不会强制执行呼叫站点文档。它只是提供了一种非常蹩脚的记录方式。我对一个强制调用站点文档的模板进行了一些实验。不过,这比实际生产代码更有趣。

http://blogs.msdn.com/jaredpar/archive/2008/04/03/reference-values-in-c.aspx

http://blogs.msdn.com/jaredpar/archive/2008/04/03/reference-values-in-c.aspx

回答by kenny

I think I would disagre with @bb and @JaredPar and I lean to the opposite side of the fence. After years of trying to support other peoples C++ code, I often find problems lurking in non-obvious side effects of reference arguments. With C#, it is obvious since you have to prefix types of arguments with 'ref'/'out' but references are potentially confusing in C++. So, I like pointers because it's really clear something is coming back up. If you don't like points, C++ is not for you.

我想我会不同意@bb 和@JaredPar,我倾向于栅栏的另一边。经过多年努力支持其他人的 C++ 代码,我经常发现问题潜伏在引用参数的非明显副作用中。使用 C#,这很明显,因为您必须使用 'ref'/'out' 作为参数类型的前缀,但引用在 C++ 中可能会造成混淆。所以,我喜欢指针,因为很明显有些东西正在恢复。如果你不喜欢积分,C++ 不适合你。

回答by i_am_jorf

I come down on the pointer side of the fence, for reasons cited here and elsewhere. However, I will say that whatever you decide, you need to be consistent and document it in your style guide.

由于这里和其他地方引用的原因,我从栅栏的指针一侧下来。但是,我会说无论您做出什么决定,您都需要保持一致并将其记录在您的风格指南中。

Google C++ style guide bansnon-const reference arguments.

Google C++ 风格指南禁止非常量引用参数。

回答by Nick

I like passing by reference if NULL does not have significance, but I can see the arguments for both. If you're careful about coding you could probably eliminate the accidental pass-by-reference objection by making sure you always pass your variables by const reference, eg:

如果 NULL 没有意义,我喜欢通过引用传递,但我可以看到两者的参数。如果您对编码很小心,您可以通过确保始终通过常量引用传递变量来消除意外的传递引用反对,例如:

myfunc( const_cast< const int& >( a ) );

// Alternatively, this approach may require additional handling 
// in the function, but it's cleaner at call point
myfunc( boost::cref( a ) );

That's a lot of extra code for little benefit, though. As Kenny pointed out, C# addressed this from the opposite end (requiring specific passing by reference), but that's not an option for C++ (unless, for example, you wrote your functions to take a reference wrapper as their parameter, like boost::ref(param)), eg:

不过,这是很多额外的代码,但收益甚微。正如 Kenny 指出的那样,C# 从另一端解决了这个问题(需要特定的通过引用传递),但这不是 C++ 的选项(除非,例如,您编写函数以将引用包装器作为它们的参数,例如 boost:: ref(param)),例如:

void myfunc( const boost::reference_wrapper< int >& a ) { ... }

Fixing the pointer problem is more problematic, though... there's no compile-time way to ensure the pointer is valid, so you end up with either run time problems for pointer issues, or run time checks, or both. Tis the nature of pointers.

修复指针问题更成问题,但是……没有编译时方法来确保指针有效,因此您最终会遇到指针问题的运行时问题,或运行时检查,或两者兼而有之。这是指针的性质。

Anyway, that's just my opinion, for what it's worth.

无论如何,这只是我的意见,对于它的价值。

回答by Nick

Something to note, if you are using stl functors, it is easier if the parameter matches the container value type.

需要注意的是,如果您使用 stl 函子,则参数与容器值类型匹配会更容易。

void foo(Bar *);

void frobnicate(vector<Bar *> vecBars)
{
   for_each(vecBars.begin(), 
            vecBars.end(), 
            ptr_fun(&foo));
}

The above code is much harder if foo takes Bar&

如果 foo 带 Bar& 上面的代码就难多了

回答by bayda

The former forces you to call the function with myfunc(&b) so the caller is aware that b will be modified

前者强制您使用 myfunc(&b) 调用函数,以便调用者知道 b 将被修改

sometimes function could accept const pointer and caller will have wrong thinking that b will be modified.

有时函数可以接受 const 指针,调用者会错误地认为 b 将被修改。

My recommendation - prefer use references everywhere where it possible (ofcourse where it needed). In case with function argument - we get benefits:
- references can't be NULL - it help us to avoid errors and unnecessary asserts or checks.
- references have only one initialization point and in function boody you always know on what thing input parameter points.

我的建议 - 更喜欢在任何可能的地方使用引用(当然在需要的地方)。在函数参数的情况下 - 我们得到好处:
- 引用不能为 NULL - 它帮助我们避免错误和不必要的断言或检查。
- 引用只有一个初始化点,在函数体中你总是知道输入参数指向什么东西。

I'm maintainer on large project. And in either cases I'm looking on function definition before call its. Ofcourse when I looking on function definition I see arguments definition by value, by reference, by const reference or by pointer.

我是大型项目的维护者。在任何一种情况下,我都会在调用它之前查看函数定义。当然,当我查看函数定义时,我会看到按值、按引用、按常量引用或按指针定义的参数。

But it seems like holy-war question, defferent peoples have different view on this point. E.g. google codding convension recomended use pointers in arguments which could be changed and allowed only const references: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments

但这似乎是圣战问题,不同的人对此有不同的看法。例如,谷歌编码约定建议在参数中使用指针,这些指针可以更改并只允许常量引用:http: //google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments

All parameters passed by reference must be labeled const.

通过引用传递的所有参数都必须标记为 const。

回答by Dan Olson

In an ideal world it comes down to whether or not the parameter is an optional output. Do you want to allow the caller to pass NULL if they don't care about it? Then use a pointer. Otherwise a reference is a better choice.

在理想的世界中,它归结为参数是否是可选输出。如果调用者不关心它,您是否希望允许调用者传递 NULL?然后使用指针。否则,参考是更好的选择。

Note that in both cases the language makes it cumbersome to document an output parameter. It's much better if the whole codebase is const correct, then the users can assume that any non-const reference or pointer parameter is an output.

请注意,在这两种情况下,语言都使得记录输出参数变得很麻烦。如果整个代码库是 const 正确的,那就更好了,那么用户可以假设任何非常量引用或指针参数都是输出。

回答by hasen

One difference, like has been mentioned before, is you can't pass a null reference, but you can pass a null pointer.

一个区别,就像之前提到的,是你不能传递一个空引用,但你可以传递一个空指针。

Another thing, also mentioned already, when you call f(a,b)there could be confusion if the caller doesn't know that fcould potentially change the value for b

另一件事,也已经提到,当你打电话时f(a,b),如果调用者不知道这f可能会改变b

However, yet another issue, which is rather subtle, but I still ran into it, is the semantics of references.

然而,另一个相当微妙但我仍然遇到的问题是引用的语义。

Pointers are passed by value, but references are not.

指针是按值传递的,但引用不是。

Which means, if you pass a parameter by pointer, you can change the pointer and make it point to something else.

这意味着,如果您通过指针传递参数,则可以更改指针并使其指向其他内容。

Consider this:

考虑一下:

void f1_ptr( type * a )
{
    a = new type(); //no change to passed parameters, you're changing the pointer which was passed by value
}

void f2_ptr( type * a )
{
    *a = some_other_value; //now you're changing the value of the parameter that was passed

   //or, if type is a class or struct:

   a->some_method_that_modifies_object(); //again, changing the parameter that was passed
}

But, when passing by reference, you can't change the reference to refer to another value. Once the reference is set, it can't be changed.

但是,通过引用传递时,您不能将引用更改为引用另一个值。一旦设置了参考,就无法更改。

void f3_ref( type& a )
{
    a = type(); //the referred variable has also changed
}

//....

type obj = type( params );

f3_ref( obj ); //obj now changed

f1_ptr( &obj ); //obj doesn't change

f2_ptr( &obj ); //obj now changed