Q: Is pass-by-value/reference defined strictly by behavior or implementation wise in C++, and can you provide an authoritative citation?
I had a conversion with a friend about pass-by-value/reference in C++. We came to a disagreement on the definition of pass-by-value/reference. I understand that passing a pointer to a function is still pass-by-value since the value of the pointer is copied, and this copy is used in the function. Subsequently, dereferencing the pointer in the function and mutating it will modify the original variable. This is where the disagreement appears.
His stance: Just because a pointer value was copied and passed to the function, performing operations on the dereferenced pointer has the ability to affect the original variable, so it has the behavior of pass-by-reference, passing a pointer to a function.
My stance: Passing a pointer to a function does copy the value of the pointer, and operations in the function may affect the original variable; however, just because it may affect the original, this behavior does not constitute it to be pass-by-reference since it is the implementation of the language that is what defines these terms, pass-by-value/reference.
Quoting from the definition given by the highest voted answer here: Language Agnostic
Pass by Reference
When a parameter is passed by reference, the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.
Pass by Value
When a parameter is passed by value, the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.
I still have an ambiguous feeling after reading these. For example, the pass by value/reference quotes can support either of our claims. Can anyone clear up the definitions of whether these definition stem from behavior or implementation and provide a citation? Thanks!
Edit: I should be a little more careful of my vocabulary. Let me extend my question with a clarification. What I mean when questioning pass-by-reference is not talking purely about the C++ implementation of & reference, but instead also the theory. In C++, is it that the & pass-by-reference is true PBR because not only can it modify the original value, but also the memory address of the value. This leads to this, example with pointers also count as PBR?
void foo(int ** bar){
*bar = *bar+(sizeof(int*));
cout<<"Inside:"<<*bar<<endl;
}
int main(){
int a = 42;
int* ptrA = &a;
cout<<"Before"<<ptrA<<endl;
foo(&ptrA);
cout<<"After:"<<ptrA<<endl;
}
The output would be that After ptrA is equal to Inside, meaning that not only can the function modify a, but ptrA. Because of this, does this define call-by-reference as a theory: being able to not only modify the value, but the memory address of the value. Sorry for the convoluted example.
You talk a lot about pointers here, which they are indeed passed by value most of the time, but you don't mention actual C++ references, which are actual references.
int a{};
int& b = a;
// Prints true
std::cout << std::boolalpha << (&b == &a) << std::endl;
Here, as you can see, both variables have the same address. Put it simply, especially in this case, references act as being another name for a variable.
References in C++ are special. They are not objects, unlike pointers. You cannot have an array of references, because it would require that references has a size. Reference are not required to have a storage at all.
What about actually passing a variable by reference then?
Take a look at this code:
void foo(int& i) {
i++;
}
int main() {
int i{};
foo(i);
// prints 1
std::cout << i << std::endl;
}
In that particular case, the compiler must have a way to send to which variable the reference is bound. Indeed references are not required to have any storage, but they are not required to not have one either. In this case, if optimizations are disabled, it is most likely that the compiler implements the behavior of references using pointers.
Of course, if optimizations are enabled, it may skip the passing and completely inline the function. In that case, the reference don't exist, or don't have any storage, because the original variable will be used directly.
Other similar optimization happens with pointers too, but that's not the point: The point is, the way references are implemented is implementation defined. They are most likely implemented in term of pointers, but they are not forced to, and the way a reference is implemented may vary from case to case. The behavior of references are defined by the standard, and really is pass-by-reference.
What about pointers? Do they count as passing by reference?
I would say no. Pointers are objects, just like int, or std::string. You can even pass a reference to a pointer, allowing you to change the original pointer.
However, pointers do have reference semantics. They are not reference indeed, just like std::reference_wrapper is not a reference either, but they have reference semantics. I wouldn't call passing a pointer "passing by reference", because you don't have an actual reference, but you indeed have reference semantics.
A lot of things have reference semantics, pointers, std::reference_wrapper, a handle to a resource, even GLuint, which are handle to an opengl object, all have reference semantics, but they are not references. You don't have a reference to the actual object, but you can change the pointed-to object through these handles.
There are other good articles and answers you can read about. They are all very informative about value and reference semantics.
isocpp.org: Reference and Value Semantics
Andrzej's C++ blog: Value semantics
Stack Overflow: What are the differences between a pointer variable and a reference variable in C++?
Passing by value/reference (you forgot one which is passing the address to the location in memory by using a pointer) is part of the implementation of C++.
There is one more way to pass variables to functions, and that is by address. Passing an argument by address involves passing the address of the argument variable (using a pointer) rather than the argument variable itself. Because the argument is an address, the function parameter must be a pointer. The function can then dereference the pointer to access or change the value being pointed to.
Take a look here at what I have always thought to be an authoritative Source: Passing Arguments by Address.
You're correct in regards to a value being copied when passing by value. This is the default behavior in C++. The advantage of passing by value into a function is that the original value cannot be changed by the function when the value is passed into it and this prevents any unwanted bugs and/or side effects when changing the value of an argument.
The problem with passing by Value is that you will incur a huge performance penalty if you pass an entire struct or class many times into your function as you will be passing entire copies of the value you are trying to pass AND in the case of a mutator method in a class, you will not be able to change the original values and will therefore end up creating multiple copies of the data you are trying to modify because you will be forced to return the new value from the function itself instead of from the location in memory where the data structure resides. This is just completely inefficient.
You only want to pass by value when you don't have to change the value of the argument.
Here is a good source on the topic of Passing Arguments by Value.
Now, you will want to use the "Pass by Reference" behavior when you do need to change the value of an argument in the case of arrays, Classes, or structs. It is more efficient to change the value of a data structure by Passing a Reference to the location in memory where the data structure resides into the function. This has the benefit that you will not have to return the new value from the function but rather, the function can then change the value of the reference you have given it directly where it resides in memory.
Take a look here to read more about about Passing an Argument by Reference.
EDIT: In regards to the issue as to whether or not you are passing a non-const by reference or by value when using a pointer, it seems to me the answer is clear. When using a pointer to a non-const, it is neither. When passing a pointer as an argument to a function, you in fact are "Passing the Value" of the ADDRESS into the function and since it is a copy of the ADDRESS of the location in memory where the non-const resides, then you are able to change the Value of the data at that location and not the value of the pointer itself. If you do not want to change the value of the data located at the address pointed to by the pointer being passed by value as an argument into your function, it is good form to make the pointer to an argument a const since the function will not be changing the value of the data itself.
Hope that makes sense.
References are different from pointers. The main reason references were introduced is to support Operator Overloading. C++ is derived from C and during the process, Pointers were inherited from C. As Stroustrup says:
C++ inherited pointers from C, so I couldn't remove them without causing serious compatibility problems.
So, effectively there are three different ways of parameters passing:
Pass by value
Pass by reference &
Pass by pointers.
Now, pass by pointer has the same effect as pass by reference. So how to decide on what you want to use? Going back to what Stroustrup said:
That depends on what you are trying to achieve:
If you want to change the object passed, call by reference or use a pointer; e.g. void f(X&); or void f(X*);
If you don't want to change the object passed and it is big, call by const reference; e.g. void f(const X&);
Otherwise, call by value; e.g. void f(X);
Ref: http://www.stroustrup.com/bs_faq2.html#pointers-and-references
Those terms are about the variable that is passed, in this case the pointer. If you pass a pointer to a function then the variable that is passed is the pointer - holding the address of the object - to an object and not the object it points to.
If you pass a pointer by value then chaning the object it is pointing to in the function would not affect the pointer that was passed to the function.
If you pass the pointer by reference then you can change in the function where the pointer is pointing to and it would modifiy the pointer that was passed to this function.
Thats how it is defined. Otherwise you could argue that if you have a global std::map<int,SomeObject> and you pass an int as key to the object, would also be a pass by reference because you can modify the objects in that global map, and the caller would see those changes. Because this int is also just a pointer to an object.
This question already has answers here:
Why pass by const reference instead of by value?
(8 answers)
Closed 8 years ago.
The point of passing by reference, I thought, was to pass in the actual variable either to save time or to modify the variable. Thus -- and this is going to make me sound stupid -- I used to think that passing a constant reference somehow temporarily changed the passed-in variable to a constant (if it wasn't already) and then changed it back to a non-constant (unless it was constant to begin with) when the function was done executing. I just learned today when I was reading C++ Primer that passing in a constant reference creates a temporary constant variable. That is,
foo(const type& obj)
is the same as
foo(const type obj)
because they both create a constant object obj and set it equal to whatever is passed in.
So what's the point of passing by constant reference??? What's the point of references anyways? They're the same thing as pointers, except that they need to be initialized and are thus less useful.
when you pass constant reference no temporary copy is created.....while if you pass constant argument new copy is created....
you can check this by printing the addresses of variable in caller function and callee function.
The right way of doing it is using a constant reference:
foo(const type& obj)
because that way the object is not copied, and that is more efficient especially if the object is big or the function is called multiple times.
No. A constant variable creates a temporary variable but a constant reference may not.
This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 9 years ago.
I haven't understand passing by reference in C++ completely. I already read related questions like the following ones.
What are the differences between a pointer variable and a reference variable in C++?
Are there benefits of passing by pointer over passing by reference in C++?
When to use references vs. pointers
But even though I understand that it is different to a pointer, I don't fully understand the concept of reference in C++. How does it work? I seems like reference is a special case of a pointer and might be implemented as such by the compiler. But it behaves different on programming level. Is that correct?
Is the concept of passing by reference a special case of passing a pointer to that value? Many times I have to decide whether to use reference or pointer while programming. Moreover I want to understand the underlying principle. Is only the memory address copied?
A reference is a pointer with some special restrictions. A reference must never be un-initialized. When a reference is created it must point to something. This is useful when wanting a "pointer" that will not be NULL.
Furthermore a reference cannot have the address it holds changed, therefor it is a constant pointer.
It has some nice syntactic sugar to allow it to use the dot operator, making it useful when changing from by-value code to by-reference code.
In practice using a reference in a function as a parameter or return value usually would signify "by address, cannot be NULL and must be a valid object". Using a pointer instead would usually signify "could be NULL, so NULL must be handle". By pointer also allows for pointer arithmetic and manipulation.
What you should use is really what you're most comfortable with, assuming you understand both. I myself prefer pointers.
Edit:
As pointed out in the comments here, you cannot take the address of a reference directly, as it will return the address of what the reference is referring to. This is yet another restriction that does not apply to an average pointer.
yes, it's essentially the same as a pointer but a nicer and safer version as the pointer address cant be changed or set to null. i see it mainly as a means to have nice function interfaces without requiring the user of the interface to worry about pointers - ie function remain simple yet the object is not copied, purely its address. class copy constructor is a prime example of where references are crucial.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
References in VB.Net
I want to pass a medium large Customer db object, but I don't want to pass it by value, because I think it would be unnecessary.
In c++ when you had a large object it was inefficient to pass it by value, because a copy was created from it, so you passed it by reference so that there was no copy (of the object passed) created. I used to pass the parameter as a constant because that way if I tried to change the object inside the function the compiler wouldn't let me so that I wouldn't harm the passed object (because it was passed by reference). Is it possible to mimick this in vb.net or is it not needed?
My strong suspicion is that you're getting confused about how values are passed in VB.
If your CustomerDb type is a class, then every expression of that type will have a value which is already a reference. By default, that reference will be passed by value - but it's still only the reference which is passed, not a whole object.
If your CustomerDb type is a structure, then you really will be passing the whole value each time - and you should strongly consider changing it to a class anyway...
Of course, when you pass a reference by value, that doesn't stop the object from being modified within the method, but it does mean that changes to the parameter variable itself aren't reflected in the calling code.
Read my article on C# parameter passing - it's much the same in VB.
In .NET, classes (which I assume Customer is) are reference types. Passing a reference type as an argument will pass a reference (pointer) to the object. So passing a class is perfectly efficient and no copy is created.
If you pass a class by reference, then the method could change the reference (pointer) and it would be reflected in the calling method.
I don't know off the top of my head if there's an easy way to make the argument read only. Since reference types do pass a reference, any changes to the object will be reflected in the original. You might need a copy if you don't want the original to be modified.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the difference between passing by reference vs. passing by value?
If I have a function that takes in some parameters and then does something with the parameters without needing to change their inherent value, is there any benefit from using pass by reference versus pass by value?
Yes. Passing by value copies the argument, which might be very expensive (or not even possible). If you want to pass by reference, but not modify the object, pass by const-reference.
As an example of an object that cannot be passed by value:
class Foo {
public:
Foo() {}
private:
Foo(const Foo&); // copy-constructor is not accessible
}
Here is the general guide:
Pass by reference when
You need to cause a side effect on the object that will be visible to the caller
or you cannot pass by value because of the lack of an accessible copy constructor or something and you need side effects
Pass by const reference when you have
A large object
and/or you cannot pass by value
and/or no need for side effects
Pass by value when
The object is small
and/or You do not need side effects
and/or You need a copy of the value to work with anyway