Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have developed a habit of using safe C++ constructs where possible, but there is one place where I'm always not sure if it's better to use references or resort to good ol' pointers.

Example code:

int FillFancyPointer(char *&ptr)
{
    ptr = NULL;

    char *tmp_ptr = static_cast<char*>(calloc(...));
    if(!ptr)
        return -1;

   ptr = tmp_ptr;
   return 0;
}

Later in code:

char *ptr = nullptr;
if(FillFancyPointer(ptr)>=0 && ptr)
   Nice();

The problem with this, IMHO, is that the ptr appears to be read only variable when looking at the code, while in reality it is modified.

The COM approach ISmthn *ptr;, CoCreate(..., &ptr) seems more pronounced. But it's also more error prone, as there is this ** stuff everywhere.

Come to think of it, output variables like std::string will also be masked with such approach.

int Foo(const string &in, string &inout)

Do you find references confusing in such places?

share|improve this question
    
What's going on in this code, anyway? It's a reference to a pointer, or a pointer to a reference, or something else? –  Stephen Gross Dec 13 '11 at 19:22
    
Right to left reading, ptr is a reference to pointer of type char. –  Coder Dec 13 '11 at 19:31
    
Just curious: Is there really a situation where this approach is warranted? It seems like there should be an more understandable way to solve the problem...? –  Stephen Gross Dec 13 '11 at 19:54
    
Slowly C++'izing a C style code... You slowly migrate away from C issues like *p[i] = b; / **p = b; / etc. at the same time having the transition period to shared_ptr<char> etc. which is incompatible with the codebase without larger code changes. –  Coder Dec 13 '11 at 20:00
1  
@kevincline: It was a hypotetical problem :D What if you could return 2 if the pointer is the same, just reallocated, and so on. The question is still, if such parameter modifications are bad or good as they are quite invisible in the code. –  Coder Dec 14 '11 at 19:47

3 Answers 3

up vote 4 down vote accepted

The problem with your code sample isn't that you take a reference, it's that you use a return code. In C++, if the operation fails, throw an exception, or if that isn't unusual, then use boost::optional, or even boost::variant<T, ErrorCode>.

Your code is very C and not C++ at all.

share|improve this answer
    
Old code maintanance & C++ifying... Although exceptions are not very good IMHO, a whole new can of worms... –  Coder Feb 24 '12 at 4:26
    
@Coder: Exceptions suck. But they're one hell of a lot better than error codes. –  DeadMG Feb 24 '12 at 4:28

If you’re concerned about mutability, make references const unless they need to be mutable, and leave it at that. A function’s name and documentation should convey its purpose and whether it intends to modify one of its parameters.

Users of the function shouldn’t need to care whether something is passed by value or reference; the “invisibility” of references—that they have the same syntax as values—is one of their strengths. The reason for introducing references to C++ in the first place was to “invisibly” support operator overloading. In addition to their consistency, they are also amenable to generic programming, which is a big thing in the C++ world. And in C++0x, it gets more interesting: you can pass variables syntactically by value, but they can be move-constructed, eliminating the need for a copy.

share|improve this answer
    
Well, move construction is usually natural, the copy construction has issues, because copy constructors usually have side effects, like copying buffers, sharing shared states etc. And unexpected behavior for move constructor is not really unexpected, vs sudden change in values passed by reference. –  Coder Dec 13 '11 at 19:54

Everything about your code example is C and not C++. I think you have bigger issues than whether you are passing a pointer by reference or not. For example, I would suggest using new and delete rather than malloc.

To answer you question directly, use references everywhere you can and pointers when you have to - ie when you need to reseat the reference. All of this is in the C++ FAQ which is a mine of brilliant information.

share|improve this answer
    
I actually prefer malloc/calloc/realloc/free over new/placement new/delete. The downside is that constructors are not called for C variants. –  Coder Feb 24 '12 at 4:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.