+2  A: 

I honestly think that this whole passing by value/passing by reference idea in C++ is misleading. Everything is pass by value. You have three cases:

  1. Where you pass a local copy of a variable

    void myFunct(int cantChangeMyValue)

  2. Where you pass a local copy of a pointer to a variable

    void myFunct(int* cantChangeMyAddress) { *cantChangeMyAddress = 10; }

  3. Where you pass a 'reference', but through compiler magic it's just as if you passed a pointer and simply dereferenced it every time.

    void myFunct(int & hereBeMagic) { hereBeMagic = 10; // same as 2, without the dereference }

I personally find it much less confusing to remember that everything is pass by value. In some cases, that value might be an address, which allows you to change things outside the function.

What you are suggesting would not allow the programmer to do number 1. I personally think that would be a bad idea to take away that option. One major plus of C/C++ is having have fine grained memory management. Making everything pass by reference is simply trying to make C++ more like Java.

Tim Sally
If you start to redefine the established meanings of pass-by-value and pass-by-reference, that's what I find misleading.
QBziZ
+1  A: 

Yeah, I'm of the opinion that that's a pretty confusing overload.

This is what microsoft has to say about the situation:

Do not confuse reference declarations with use of the address-of operator. When & identifier is preceded by a type, such as int or char, then identifier is declared as a reference to the type. When & identifier is not preceded by a type, the usage is that of the address-of operator.

I'm not really great on C or C++, but I get bigger headaches sorting out the various uses of * and & on both languages than I do coding in assembler.

Ryan
MSalters
+10  A: 

A compiler option that totally changes the meaning of a section of code sounds like a really bad idea to me. Either get use to the C++ syntax or find a different language.

Andy Brice
+1  A: 

The best advice is to make a habit of thinking about what you really want to happen. Passing by reference is nice when you don't have a copy constructor (or don't want to use it) and it's cheaper for large objects. However, then mutations to the parameter are felt outside the class. You could instead pass by const reference -- then there are no mutations but you cannot make local modifications. Pass const by-value for cheap objects that should be read-only in the function and pass non-const by-value when you want a copy that you can make local modifications to.

Each permutation (by-value/by-reference and const/non-const) has important differences that are definitely not equivalent.

Pat Notz
+1  A: 

When you pass by value, you are copying data to the stack. In the event that you have an operator= defined for the struct or class that you are passing it, it gets executed. There is no compiler directive I am aware of that would wash away the rigmarole of implicit language confusion that the proposed change would inherently cause.

A common best practice is to pass values by const reference, not just by reference. This ensures that the value cannot be changed in the calling function. This is one element of a const-correct codebase.

A fully const-correct codebase goes even further, adding const to the end of prototypes. Consider:

void Foo::PrintStats( void ) const {
   /* Cannot modify Foo member variables */
}

void Foo::ChangeStats( void ) {
   /* Can modify foo member variables */
}

If you were to pass a Foo object in to a function, prefixed with const, you are able to call PrintStats(). The compiler would error out on a call to ChangeStats().

void ManipulateFoo( const Foo &foo )
{
    foo.PrintStats();  // Works
    foo.ChangeStats(); // Oops; compile error
}
sludge
+2  A: 

I'd rather not abuse references any more by making every (non-qualified) parameter a reference.

The main reason references were added to C++ was to support operator overloading; if you want "pass-by-reference" semantics, C had a perfectly reasonable way of doing it: pointers.

Using pointers makes clear your intention of changing the value of the pointed object, and it is possible to see this by just looking at the function call, you don't have to look at the function declaration to see if it's using a reference.

Also, see

I do want to change the argument, should I use a pointer or should I use a reference? I don't know a strong logical reason. If passing ``not an object'' (e.g. a null pointer) is acceptable, using a pointer makes sense. My personal style is to use a pointer when I want to modify an object because in some contexts that makes it easier to spot that a modification is possible.

from the same FAQ.

aib
A: 

there are something not clear. when you say:

int b(b &param);

what did you intend for the second 'b'? did you forget to introduce a type? did you forget to write differently with respect to the first 'b'? don't you think it's clear to write something like:

class B{/*something...*/};
int b(B& param);

Since now, I suppose that you mean what I write.

Now, your question is "don't you think will be better that the compiler will consider every pass-by-value of a non-POD as pass-by-ref?". The first problem is that it will broke your contract. I suppose you mean pass-by-CONST-reference, and not just by reference.

Your question now is reduced to this one: "do you know if there's some compilers directive that can optimize function call by value?"

The answer now is "I don't know".

ugasoft
Augusto Radtke
+10  A: 

I guess you're missing the point of C++, and C++ semantics. You missed the fact C++ is correct in passing (almost) everything by value, because it's the way it's done in C. Always. But not only in C, as I'll show you below...

Parameters Semantics on C

In C, everything is passed by value. "primitives" and "PODs" are passed by copying their value. Modify them in your function, and the original won't be modified. Still, the cost of copying some PODs could be non-trivial.

When you use the pointer notation (the * ), you're not passing by reference. You're passing a copy of the address. Which is more or less the same, with but one subtle difference:

typedef struct { int value ; } P ;

/* p is a pointer to P */
void doSomethingElse(P * p)
{
   p->value = 32 ;
   p = malloc(sizeof(P)) ; /* Don't bother with the leak */
   p->value = 45 ;
}

void doSomething()
{
   P * p = malloc(sizeof(P)) ;
   p->value = 25 ;

   doSomethingElse(p) ;

     int i = p->value ;
   /* Value of p ? 25 ? 32 ? 42 ? */
}

The final value of p->value is 32. Because p was passed by copying the value of the address. So the original p was not modified (and the new one was leaked).

Parameters Semantics on Java and C Sharp

It can be surprising for some, but in Java, everything is copied by value, too. The C example above would give exactly the same results in Java. This is almost what you want, but you would not be able to pass primitive "by reference/pointer" as easily as in C.

In C#, they added the "ref" keyword. It works more or less like the reference in C++. The point is, on C#, you have to mention it both on the function declaration, and on each and every call. I guess this is not what you want, again.

Parameters Semantics on C++

In C++, almost everything is passed by copying the value. When you're using nothing but the type of the symbol, you're copying the symbol (like it is done in C). This is why, when you're using the *, you're passing a copy of the address of the symbol.

But when you're using the &, then assume you are passing the real object (be it struct, int, pointer, whatever): The reference.

It is easy to mistake it as syntaxic sugar (i.e., behind the scenes, it works like a pointer, and the generated code is the same used for a pointer). But...

The truth is that the reference is more than syntaxic sugar.

  • Unlike pointers, it authorizes manipulating the object as if on stack.
  • Unline pointers, when associatied with the const keyword, it authorizes implicit promotion from one type to another (through constructors, mainly).
  • Unlike pointers, the symbol is not supposed to be NULL/invalid.
  • Unlike the "by-copy", you are not spending useless time copying the object
  • Unlike the "by-copy", you can use it as an [out] parameter
  • Unlike the "by-copy", you can use the full range of OOP in C++ (i.e. you pass a full object to a function waiting an interface).

So, references has the best of both worlds.

Let's see the C example, but with a C++ variation on the doSomethingElse function:

struct P { int value ; } ;

// p is a reference to a pointer to P
void doSomethingElse(P * & p)
{
   p->value = 32 ;
   p = (P *) malloc(sizeof(P)) ; // Don't bother with the leak
   p->value = 45 ;
}

void doSomething()
{
   P * p = (P *) malloc(sizeof(P)) ;
   p->value = 25 ;

   doSomethingElse(p) ;

     int i = p->value ;
   // Value of p ? 25 ? 32 ? 42 ?
}

The result is 42, and the old p was leaked, replaced by the new p. Because, unlike C code, we're not passing a copy of the pointer, but the reference to the pointer, that is, the pointer itself.

When working with C++, the above example must be cristal clear. If it is not, then you're missing something.

Conclusion

C++ is pass-by-copy/value because it is the way everything works, be it in C, in C# or in Java (even in JavaScript... :-p ...). And like C#, C++ has a reference operator/keyword, as a bonus.

Now, as far as I understand it, you are perhaps doing what I call half-jockingly C+, that is, C with some limited C++ features.

Perhaps your solution is using typedefs (it will enrage your C++ colleagues, though, to see the code polluted by useless typedefs...), but doing this will only obfuscate the fact you're really missing C++ there.

As said in another post, you should change your mindset from C development (of whatever) to C++ development, or you should perhaps move to another language. But do not keep programing the C way with C++ features, because by consciously ignoring/obfuscating the power of the idioms you use, you'll produce suboptimal code.

Note: And do not pass by copy anything else than primitives. You'll castrate your function from its OO capacity, and in C++, this is not what you want.

Edit

The question was somewhat modified (see http://stackoverflow.com/revisions/146271/list ). I let my original answer, and answer the new questions below.

What you think about default pass-by-reference semantics on C++? Like you said, it would break compatibility, and you'll have different pass-by for primitives (i.e. built-in types, which would still be passed by copy) and structs/objects (which would be passed as references). You would have to add another operator to mean "pass-by-value" (the extern "C" is quite awful and already used for something else quite different). No, I really like the way it is done today in C++.

[...] the reference operator seems to me a way to get the variable address, that's the way I used for getting pointers. I mean, it is the same operator but with different semantic on different contexts, doesn't that feel a little bit wrong for you too? Yes and no. Operator >> changed its semantic when used with C++ streams, too. Then, you can use operator += to replace strcat. I guess the operator & got used because its signification as "opposite of pointer", and because they did not want to use yet another symbol (ASCII is limited, and the scope operator :: as well as pointer -> shows that few other symbols are usable). But now, if & bothers you, && will really unnerve you, as they added an unary && in C++0x (a kind of super-reference...). I've yet to digest it myself...

paercebal
I'm sorry, I think it would be necessary to be more explicit. I never pass anything more than 32 bits by value, and that's almost every class of mine, that's why I wished it could be default. I also use const a lot. I'm not missing semantics, I wish to *change* it.
Augusto Radtke
Augusto Radtke
A: 

I think that c++ become very messy if you start to mix all the kind of available parameters, with their const variations.

It gets rapidly out of hand to trak all the copy constructors calls, all the dereferences overloaded and so on.

Lorenzo Boccaccia
You got the point on simplifying syntax and forcing one specific semantic. These proposed changes are a way to overcome that multiple possibilities mess. I think one of main critics of C++ is that it try to make too much things.
Augusto Radtke
A: 

In other words, you want C++ to be more like Java?

tloach
Yes and no. Yes because in Java it "feels" like you are passing everything by reference, and no because you are really not passing by reference in Java, it's by value believe or not. :)
Augusto Radtke