C++ functions: ampersand vs asterisk

前端 未结 9 1871
情书的邮戳
情书的邮戳 2020-12-13 03:43

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)

相关标签:
9条回答
  • 2020-12-13 04:22

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

    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&

    0 讨论(0)
  • 2020-12-13 04:24

    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 bans non-const reference arguments.

    0 讨论(0)
  • 2020-12-13 04:24

    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 f could potentially change the value for 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
    
    0 讨论(0)
  • 2020-12-13 04:36

    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.

    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

    #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

    0 讨论(0)
  • 2020-12-13 04:36

    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:

    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:

    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.

    0 讨论(0)
  • 2020-12-13 04:38

    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)

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

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

    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.

    0 讨论(0)
提交回复
热议问题