how to modify an object using *& in C++ - c++

I'm new to C++ and I'm getting myself confused over concepts involving pointers/references
If I had a function such as
void func(classA *&size) {
//this is the part I don't understand what to do
}
if size had width and length, how would I change just length? (basically modify an object using *&)

Since size is a reference to the type classA*, it behaves as an alias for a pointer to a classA object, and can be used interchangeably with any other name for that object. Therefore, you would modify the object pointed to like so:
size->length = 3;
which is the same as what you would write if size had declared type classA* rather than classA*&.

The function you describe takes a reference to a pointer as an argument.
This implies that the function intends to modify the pointer itself.
This code is already smelling bad. It is essentially sharing ownership of the pointed-to object with none of the protection offered by a smart pointer (unique_ptr, shared_ptr) reference, and no annotation to indicate that this pointer is an observer (see the documentation for the soon-to-be-standard observer_ptr).
You want to know what to do inside the function. Well it depends. The argument is set up to both communicate the address of an object to the function and receive the address of a (possibly different) object from the function.
If this is what you want, you probably already know what to do.
If all you want to do is pass a reference to an object, pass just a reference. If you want to pass a pointer to the object, pass just a pointer.
If you really do want to pass in a pointer and receive a possibly different pointer, I would suggest that the function should look more like this:
classA* func(classA* a); // returns either a or another classA
Even better might be this:
std::unique_ptr<classA> func(std::unique_ptr<classA> a);
Because now intent and semantics are concreted into the interface. The caller is now unable to misuse the function (barring deliberate self-harm).

Related

CppCoreGuidlines R.33 Why pass `unique_ptr` by reference?

The CppCoreGuidlines rule R.33 suggests to
Take a unique_ptr<widget>& parameter to express that a function
reseats the widget.
Reason Using unique_ptr in this way both documents and enforces the
function call’s reseating semantics.
Note “reseat” means “making a pointer or a smart pointer refer to a
different object.”
I don't understand why we should pass by reference when reseat means "making a pointer or a smart pointer refer to a different object.”
When the function's purpose is to reseat/change the underlying object the pointer is pointing to, aren't we stealing the ownership from the caller this way and therefore should pass the unique_ptr by value, hence moving it and transferring ownership?
Is there an example that explains why passing a unique_ptr by reference is recommended?
When the function's purpose is to reseat/change the underlying object the pointer is pointing to, aren't we stealing the ownership from the caller this way
No. Neither when we "reseat" a pointer, nor when we change the pointed object, do we take ownership of the pointer i.e. we aren't transferring the ownership.
Is there an example that explains why passing a unique_ptr by reference is recommended?
Here is an example of a function that "reseats" a unique pointer:
void reseat(std::unique_ptr<widget>& ptr) {
ptr = std::make_unique<widget>();
}
If you tried to use a reference to const, then that wouldn't compile at all. If you tried to use a non-reference parameter, then the argument pointer wouldn't be modified and thus the behaviour wouldn't be as desired. The caller would be forced to move their pointer leaving it always null.
You could modify the example to use a pointer to unique pointer, but references are recommended because it isn't possible to pass null by mistake. A reference wrapper would also work, but it would be unnecessarily complicated.
In case we make it point somewhere else, what happens to the object it pointed before?
If a unique pointer points to something other than null, then making it point elsewhere will cause the previously pointed object to be deleted.
Aren't we leaking memory in this case?
No.
Note that the example is simple in order to be easy to understand. Typically I wouldn't recommend to write such function and instead considering to write a function that returns the new unique pointer, and let the caller "reseat" the pointer themselves. But that depends on details.

Is pass-by-value/reference defined implementation or behavior wise?

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.

C++: Why can a statically created variable by passed to a function expecting a reference?

I've been programming in C++ for a while but certainly wouldn't call myself an expert. This question isn't being asked to solve a practical problem that I have, it's more about understanding what C++ is doing.
Imagine I have a function that expects a single paramater:
void doSomething(SomeClass& ref)
{
// do something interesting
}
(Note: the parameter is a reference to SomeClass) Then I call the function like this:
int main(int argc, char *argv[])
{
SomeClass a;
doSomething(a);
}
Why is this legal C++? The function is expecting a reference to SomeClass, but I'm passing it a statically allocated variable of type SomeClass. A reference is like a pointer no? If we were to replace the reference with a pointer the compiler complains. Why is the reference different to a pointer in this way, what's going on behind the scenes?
Sorry if this is a stupid question, it's just been buggin me!
I think you'd understand this better if you stopped thinking of references as being similar to pointers. I would say there are two reasons why this comparison is made:
References allow you to pass objects into functions to allow them to be modified. This was a popular use case of pointers in C.
The implementation of pointers and references is usually pretty much the same once it's compiled.
But they are different things. You could think about references as a way of giving a new name to an object. int& x = y; says that I want to give a new name to the object I currently refer to as y. This new name is x. Both of those identifies, x and y, both refer to the same object now.
This is why you pass the object itself as a reference. You are saying that you want the function to have its own identifier to refer the object that you are passing. If you don't put the ampersand in the parameter list, then the object will be copied into the function. This copying is often unnecessary.
Your code is incorrect - SomeClass a(); is a forward declaration of a function a returning a SomeClass instance - such a declaration is not valid at function scope.
Assuming you meant SomeClass a;:
A reference is quite similar to a pointer in most practical ways - the main difference is that you cannot legally have a reference to NULL, whereas you can have a pointer to NULL. As you've noticed, the syntax for pointers and references is different - you can't pass a pointer where a reference is expected.
If you think of a reference as a "pointer that can't be null and can't be made to point elsewhere" you're pretty much covered. You're passing something which refers to your local a instance - if doSomething modifies its parameter then it's really directly modifying your local a.
SomeClass a();
This is a function signature, not an object.
It should be
SomeClass a; // a is an object
Then your code is valid.
Why is this legal C++?
(assuming you fixed the previous point)
C++ standard say that if your function attribute is a reference, then you should provide an object that have a name (an l-value). So here, it's legal. If it was a const reference, you could even provide a temporary (an r-value, that have no name).
The function is expecting a reference
to SomeClass, but I'm passing it a
statically allocated variable of type
SomeClass.
It's expecting a reference to an non-const instance of SomeClass, that is what you did provide.
That instance is not static, it's just allocated on the stack. The allocation of an object have nothing to do with the way it can be manipulated, only the scope does. The way the object is alloced (on the stack like here, or on the heap by using new/delete) only tells the lifetime of the object. Even a static object could be passed in your function, as far as it's not const.
I think you're mixing some language concepts here...
A reference is like a pointer no?
No.
A reference is a "nickname" of an object. No more, no less.
Okay, in fact it is implemented as a pointer with special rules but it's not true in every use: the compiler is free to implement it in whatever way it want.
In case of a function attribute, it's often implemented as a pointer. But you don't have to even know about it.
For you, it's just the nickname of an object.
If we were to replace the reference
with a pointer the compiler complains.
Why is the reference different to a
pointer in this way, what's going on
behind the scenes?
I guess your first error did make things fuzzy for you?
You're not passing it "a statically allocated variable of type SomeClass", you're passing it a reference to a SomeClass object you created on the stack in main().
Your function
void doSomething(SomeClass& ref)
Causes a reference to a in main to be passed in. That's what & after the type in the parameter list does.
If you left out the &, then SomeClass's (a's) copy constructor would be called, and your function would get a new, local copy of the a object in main(); in that case anything you did to ref in the function wouldn't be seen back in main()
Perhaps your confusion arises from the fact that if you have two functions:
void doThingA(int a) {
a=23;
}
void doThingB(int &a) {
a=23;
}
The calls to them look the same, but are in fact very different:
int a=10;
doThingA(a);
doThingB(a);
The first case, doThingA(int), creates a completely new variable with the value 10, assignes 23 to it and returns. The original variable in the caller remains unchanged. In the second case, doThingB(int&), where the variable is passed by reference, a new variable is create with the same address as the variable passed in. This is what people mean when they say passing by reference is like passing by pointer. Because both variables share the same address (occupy the memory location) when doThingB(int&) changes the value passed in, the variable in the caller is also changed.
I like to think of it as passing pointer without all that annoying pointer syntax. Having said that though, I find functions that modify variables passed by reference to be confusing, and I almost never do it. I would either pass by const reference
void doThingB(const int &a);
or, if I want to modify the value, explicitly pass a pointer.
void doThingB(int *a);
Reference is not a pointer. You simply pass parameters as "by value" and use-it . Under the hood only a pointer will be used, but this is just under the hood.
A reference is nothing at all like a pointer, it is an alias - a new name - for some other object. That is one reason for having both!
Consider this:
Someclass a;
Someclass& b = a;
Someclass& c = a;
Here we first create an object a, and then we say that b and c are other names for the same object. Nothing new is created, just two additional names.
When b or c is a parameter to a function, the alias for a is made available inside the function, and you can use it to refer to the actual object.
It is that simple! You don't have to jump through any loops with &, *, or -> like when using pointers.
Though the question has been already answered adequately, I can't resist sharing few more words on the related language feature of "References in C++".
As C programmers, we have two options available when passing variables to functions:
Pass the value of the variable (creating a new copy)
Pass the pointer to the variable.
When it comes to C++, we are usually dealing with objects. Copying such objects on each function call that needs to work on that object is not recommended due to space (and also speed) considerations. There are benefits involved with passing the variable address (via the pointer approach), and though we can make the pointer 'const' to avoid any changes through the pointer, the syntax with pointers is rather clumsy (miss the dereference operator at a place or two and end up spending hours debugging!).
C++, in providing 'references', packages the best of both options:
The reference can be understood to be as good as passing the address
The syntax to use the reference is the same as working on the variable itself.
The reference would always point to 'something'. Hence no 'null-pointer' exceptions.
Additionally, if we make the reference 'const', we disallow any changes to the original variable.

Any Default Pass By Reference DataTypes in C++?

I understand that unlike C# ( where class is passed by reference and struct is passed by default), both structure and class in C++ are passed by value into a method, unless it is explicitly modified to pass by reference.
i.e.,
// this is a method that passes by reference
void PassReferenceOp(MyClass &myclass, MyStruct &myStruct)
{
}
// this is a method that passes by value
void PassReferenceOp(MyClass myclass, MyStruct myStruct)
{
}
My question is, is it that there is no data structure, data types in C++ that passes into a method by reference? That no matter I am using std::list, std::list::iterator,std::map, or any data types I create, be it struct or class, all are pass by reference?
There are no default pass by reference types. Of course, there are references which are passed by value (most notably, smart pointers), the difference between which you could argue for a while.
Not that I see the importance. Adding an & is hardly the epitome of difficulty or time wastage.
The closest to what you want is not pass-by-reference but using pointers.
References both in Java and C# are more closely related to pointers than to C++ references: A reference in C++ is an alias to the object, equivalent to the ref keyword in C#, while a reference in C#/Java is an entity that refers (points) to the real instance (as a pointer in C/C++).
The following two are equivalent (assuming a struct type in C#):
void foo( type& param ); // c++
void foo( ref type param ); // c#
Now for reference types, the equivalent would be:
void foo( type* param ); // c++
void foo( type param ); // c#
With the difference that pointers in c++ are not automatically dereferenced, that is you have to use operator-> instead of . to access members.
C++ has different argument passing and assignment semantics. Whether something is passed by value, by reference, or by pointer, is not determined by its type. Argument passing and assignment is always explicit.
Nope, no such type exists.
And (part of) the reason for this is that it just wouldn't make sense in C++. In C++, it makes a big difference whether an object is passed by value or reference, so the function needs to know how its parameter is passed.
In your code snippet, when implementing the first function, we know that we are given two references when the function is called: so any modification we make to these objects will be visible to the caller.
In the second function, we know that we are given two objects by value, meaning we can modify them freely, and that their destructors will be called at the end of the function.
If there was a sneaky type that broke this guarantee, and turned out to be a reference anyway, we could make our code blow up in all sorts of new and exciting ways.
Take a simple template function like this:
template <typename T>
T make_default() { return T(); }
If T is such a hypothetical "reference type", then this would be undefined behavior: it would create a local instance, and then return a reference to it. A reference to the object that just went out of scope and was deleted when the function returned.
Such reference types just don't really work well unless you have a garbage collector and throw away deterministic destruction, which is a pretty major C++ feature.
In C++, ownership is important. In order to write correct code, I need to know who owns every object. When is it created, when is it destroyed? A reference doesn't keep the object it points to alive, so if you're not careful, it can end up pointing to an object that no longer exists, as in my little template example above. We need to know whether or not the object we're working with is a reference.
By default, all C++ parameters are passed by value. Use & to indicate a reference.

Operator & and * at function prototype in class

I'm having a problem with a class like this:
class Sprite {
...
bool checkCollision(Sprite &spr);
...
};
So, if I have that class, I can do this:
ball.checkCollision(bar1);
But if I change the class to this:
class Sprite {
...
bool checkCollision(Sprite* spr);
...
};
I have to do this:
ball.checkCollision(&bar1);
So, what's the difference?? It's better a way instead other?
Thank you.
In both cases you are actually passing the address of bar1 (and you're not copying the value), since both pointers (Sprite *) and references (Sprite &) have reference semantics, in the first case explicit (you have to explicitly dereference the pointer to manipulate the pointed object, and you have to explicitly pass the address of the object to a pointer parameter), in the second case implicit (when you manipulate a reference it's as if you're manipulating the object itself, so they have value syntax, and the caller's code doesn't explicitly pass a pointer using the & operator).
So, the big difference between pointers and references is on what you can do on the pointer/reference variable: pointer variables themselves can be modified, so they may be changed to point to something else, can be NULLed, incremented, decremented, etc, so there's a strong separation between activities on the pointer (that you access directly with the variable name) and on the object that it points to (that you access with the * operator - or, if you want to access to the members, with the -> shortcut).
References, instead, aim to be just an alias to the object they point to, and do not allow changes to the reference itself: you initialize them with the object they refer to, and then they act as if they were such object for their whole life.
In general, in C++ references are preferred over pointers, for the motivations I said and for some other that you can find in the appropriate section of C++ FAQ.
In terms of performance, they should be the same, because a reference is actually a pointer in disguise; still, there may be some corner case in which the compiler may optimize more when the code uses a reference instead of a pointer, because references are guaranteed not to change the address they hide (i.e., from the beginning to the end of their life they always point to the same object), so in some strange case you may gain something in performance using references, but, again, the point of using references is about good programming style and readability, not performance.
A reference cannot be null. A pointer can.
If you don't want to allow passing null pointers into your function then use a reference.
With the pointer you need to specifically let the compiler know you want to pass the address of the object, with a reference, the compiler already knows you want the ptr. Both are ok, it's a matter of taste, I personally don't like references because I like to see whats going on but thats just me.
They both do the (essentially) same thing - they pass an object to a function by reference so that only the address of the object is copied. This is efficient and means the function can change the object.
In the simple case you give they are equivalent.
Main differences are that the reference cannot be null, so you don't have to test for null in the function - but you also cannot pass a null object if the case of no object is valid.
Some people also dislike the pass by reference version because it is not obvious in the calling code that the object you pass in might be modified. Some coding standards recommend you only pass const references to functions.