I'm trying to find out/understand exactly how you access data of an object using free functions.
So my free functions look like this (header wise anyways):
#ifndef CDSUPPORTFUN_H
#define CDSUPPORTFUN_H
void DisplayCDS(CDX *pCD1, CDX *pCD2, CDX *pCD3);
void ShowCosts(CDX &CD1, CDX &CD2, CDX &CD3);
void MemoryReturn(CDX *pCD1, CDX *pCD2,CDX *pCD3);
#endif
Then I have the implementation for what each does. My question is, exactly what do I input into my Main.cpp to access these functions? What information must I pass in the Main.cpp when I call them?
For example, when I use:
DisplayCDS(pCD1, pCD2, pCD3);
My data is displayed as intended. However is this still passing with a pointer? And how should it look if I am passing my reference?
--
EDIT: Since ShowCosts is passing by reference would the appropriate syntax to retrieve it be:
CD1.ReturnCosts();
To clear things up, there are two ways to pass by reference. You can pass pointers, which point to an instance of an object. Or you pass the actual object to the function, and have the function create references to those objects. To pass by reference with pointers (the way you have it):
Define your function as:
void DisplayCDS(CDX *pCD1);
and in your Main, call it as:
CDX* pCD1;
*pCD1 = something;
DisplayCDS(pCD1);
Alternatively, if you don't like pointers, you can define your function to take references and pass an actual object to it rather than a pointer. To do this:
Define your function as:
void DisplayCDS(CDX& CD1);
and in your Main, call it as:
CDX CD1;
CD1 = something;
DisplayCDS(CD1);
These two syntaxes accomplish the same thing. You have passed a reference to your function and not copied the object. Note that there will be a difference in how you use pCD1 or CD1 in your function now. If using pointers, you'll have to use pCD1 as:
pCD1->CD1MemberVar = blah;
or
*pCD1.CD1MemberVar = blah;
If you used the second syntax, you'll be able to use the object in your function as normal:
CD1.CD1MemberVar = blah;
Just to further demonstrate how pointers work, you could also use this method, which is a combination of the previous two, and is unnecessarily confusing.
Define your function as
DisplayCDS(CDX& CD1);
And in Main:
CDX* CD1;
*CD1 = something;
DisplayCDS(*CD1);
All of these examples should work...I prefer using the CDX& syntax to avoid the use of *'s all over the place. And ->'s.
EDIT: As pointed out in the comments, passing a pointer is not technically "passing by reference". It is passing an object (a pointer) that points to your object in memory.
If pCD1 etc are pointers, then ShowCosts(*pCD1, *pCD2, *pCD3); would pass references.
My question is, exactly what do I input into my Main.cpp to access these functions? What information must I pass in the Main.cpp when I call them?
First, you must include the header that declares them: #include "cdssupportfun.h" (or similar). Second you need to pass the parameters specified in the function signatures: CDX* is a pointer to a CDX, and CDX& means that it expects an object that can be passed by non-const reference - so basically a non-temporary, non-const CDX object.
DisplayCDS(pCD1, pCD2, pCD3);
has as parameters pointers to pCD1. To pass by reference, you can for example call:
ShowCosts(*pCD1, *pCD2, *pCD3);
which dereferences the pointers, and passes the objects they point to by reference.
Related
I am trying to create a speed distance and time calculator that is as efficient as possible and would like to refer to call a function using a pointer that changes according to input but am not sure how to do so. I have tried many different things:
My best attempt:
// Inside class Math
double calcSpeed(double distance, double time); // These functions return a double value of the formula (non static)
double calcDistance(double speed, double time);
double calcTime(double speed, double distance);
// Inside Main
typedef double (Math::*FuncChosen)(double first, double second);
FuncChosen p = &Math::calcSpeed; // This changes according to input to different functions in Math class with same parameter types and return types
p(1, 2); // Not a function, how can I non explicitly call the function?
Is there a way to call this function without explicitly referring to it using pointers or otherwise. Like calling a function from a pointer that changes according to input?
I don't really know where to start and what to use as everything I try is illegal. I basically want to chose the function at runtime without using several ifs and thus avoiding repetition. (I have found people with similar problems but haven't found an efficient way of doing it for my purpose.)
Thanks in advance,
And, yes, I am new to C++ and haven't done much with pointers/references and memory.
Edit: For reference, the finished, complete code after corrections - compilable
You haven't included an MCVE, but the comments and code indicate the functions are non-static member functions inside class Math. The type FuncChosen is a pointer to member function.
Pointers to members are weird beasts. It's not really a pointer, as it doesn't point to anything directly. Think of a pointer to member as an "identifier within the class." So, p identifies a particular member function (such as calcSpeed). Just as you can normally call a member function only by calling it on an object, you need to supply an object to call through the pointer to member. So, for example, if you have this code:
Math m;
double res = m.calcSpeed(1.0, 2.0);
Then the equivalent with the pointer-to-member p would be:
Math m;
FuncChosen p = &Math::calcSpeed;
(m.*p)(1.0, 2.0);
The operator .* (and the corresponding ->*) are used to dereference a pointer to member.
For completeness: The above applies to non-static member functions. If calcSpeed etc. were static member functions instead, you would use normal pointers to functions to refer to them.
A non-static function cannot be called without an object. Answer this: can you call calcSpeed like this?
calcSpeed(10.4, 444.0);
No. Because it needs an object on left.
Math o;
o.calcSpeed(10.4, 444.0);
You can hold address to this method, but you must call it using the object:
(o.*p)(10.4, 444.0);
ADD
If the object is referred by a pointer (Math* po = &o;), the ->* operator needs to be used:
(po->*p)(10.4, 444.0);
Which is same as:
((*po).*p)(10.4, 444.0);
This question already has answers here:
What is a reference variable in C++?
(12 answers)
Closed 8 years ago.
Facts that I have known:
There are three types of variables in C++: variables, pointers and references.
Variables is kinda label for the memory that stores the actual data.
Pointers stored the address of the variables.
References are alias for the variables.
My questions:
By observation, the use of variables names and references is exchangeable. Is that true?
What is the difference between passing a variable name as parameter and passing a reference? e.g.,
void func(int a); vs void func2(int& b);
Thanks a million!
Here is a way to understand the difference:
Objects that can change state are also called "variables".
Pointers are objects (variable or not). They have a state.
References are "nicknames". They don't have a state, but expose the state of the refereed object (which is why you can't re-assign a reference, it's not an actual object).
Now, in some cases references might be implemented as pointers, but from the language point of view, references are just not pointers, they really are additional names for an object already existing.
As pointers are objects, and have a state, passing pointers to functions will copy that state, the pointer's state, not the pointee's state. However, references have no state, so if you pass a reference to a function, it's the refereed object that you pass (by copy).
By observation, the use of variables names and references is
exchangeable. Is that true?
"References are nickname" is the best way to understand references.
What is the difference between passing a variable name as parameter
and passing a reference? e.g.,
void func(int a); vs void func2(int& b);
The first implementation ask for a copy of the object passed. That is, internally func() can do anything to a, without changing the object that was passed to func() because internally func() made a copy of that object and manipulates the copy, not the original.
The second implementation ask for "a nickname for an object already existing". First, the object have to exist and if passed, a nickname for it will be created inside the function. That nickname, the reference b, is still a nickname for the original object. This mean that any manipulation done to b will affect the original object passed to func2().
func() signature says "I need this data but I will not modify the original object passed.".
func2() signature says "I need an object that I WILL certainly modify, pass it so that I can modify it".
Bonus stage:
At this point, if you don't know yet about const, that might be useful: in function signatures const is used with references to specify the arguments that are "read-only".
Let me clarify:
void func3( const int& b);
Here func3 says: "I need to access to an object, but really I will not make a copy of it. However I guarantee that I will not change that object".
So, why would we need that? Because some objects are expensive to copy. int is cheap to copy so most people will just pass it and func() and func3() are basically equivalent (depends on implementation but generally true).
If however we want to pass, says, a very big object, like a data buffer, we really don't want to copy it again and again just to apply some algorithms.
So we do want to pass it by reference. However, depending on the function, sometime you want to extract information and work with it, so you only need "read-only" access to the argument. In this case you use const Object&. However, if you need to apply the algorithm to the object passed, you need to be able to modify it, which you could call "write-access". In this case, you need to use a normal reference.
Asking for a copy basically mean that you want to manipulate an object that is the same state than the passed object, but is not the passed object.
To summarize:
func( T object ) : I want to have a copy of an object of type T;
func( T& object ) : I want to have "write-access" to an object of type T - assume that I will modify that object!;
func( const T& object ) or func( T const & object ) // which are the same : I want to read the state of an object, but I guarantee you that I will not modify it, I want "read-only" access.
Actually, the "read-only" guarantee could be violated using const_cast<> but that's a different story and it's only used in some very very very narrow cases.
Last thing you need to know is that if you have a member function, then you can do:
class K{
public:
void func() const; // see the const?
};
In this specific case, what you say is that inside the function, which is basically equivalent to:
void func( const K* this );
In this case you can see that this is a pointer but it's pointing to a const object. This mean that func() guarantee that the object it is member of (this) is never modified through this function (except some specific cases, see mutable keyword, another long story).
Let's say you have these two functions:
void addone(int a) {
a += 1;
}
void addone_bis(int &a) {
a += 1;
}
If you call the first function in your main function, the value will only change in the function addone and not in the main, whereas if you call addone_bis the value of a will also be changed in the main function.
int main() {
int test_a = 10;
int test_b = 11;
addone(test_a);
// test_a still equals 10.
addone_bis(test_b);
// test_b now equals 12.
}
Did I correctly answer to your question?
Your first example is what is known as PASSING BY VALUE. What this means is that a copy of the ACTUAL value is passed into the routine.
When passing in the way of your second example, this is what is known as PASSING BY REFERENCE. A reference is ESSENTIALLY a passing of the variable into the routine such that its ACTUAL VALUE can be modified by the called routine without DE-REFERENCING.
In my project, there is a definition of a function call like this.
int32 Map(void * &pMemoryPointer)
In the calling place, the paramenter passed is void*, why cant we just receive it as a pointer itself, instead of this?
Without knowing what the Map function does, I'd guess that it sets the pointer. Therefore it has to be passed by reference.
Using a reference to a pointer, you can allocate memory and assign it to the pointer inside the function. For example
void DoSomething(int*& pointerReference)
{
// Do some stuff...
pointerReference = new int[someSize];
// Do some other stuff...
}
The other way to make functions like that is to return the pointer, but as the Map function in the question returns something else that can't be used.
Reading it backwards, this means that pMemoryPointer is a reference (&) to a pointer (*) to void. This means that whatever pointer you pass gets referenced, and any modification that the function will do to pMemoryPointer will also affect the original (passed) pointer (e.g. changing the value of pMemoryPointer will also change the value of the original pointer).
why cant we just receive it as a pointer itself, instead of this?
That's because by doing that, you are copying the pointer and any change that you'll make to the copy doesn't reflect to the original one.
void im_supposed_to_modify_a_pointer(void* ptr) { // Oh no!
ptr = 0xBADF00D;
}
int* my_ptr = 0xD0GF00D;
im_supposed_to_modify_a_pointer(my_ptr);
ASSERT(my_ptr == 0xBADF00D) // FAIL!
That's a weird function prototype IMHO, but it means
(Update) that the Map function accepts a reference to a void pointer as a parameter.
So I think, it is equivalent to declaring the function like this:
int32 Map(void** pMemoryPointer)
Lets say I have a class "A" and this function:
void initializationFunction(A* classPointer)
{
...
...
classPointer = new A(.....);
}
I write:
A* classPointer;
Then I pass this pointer to this function:
initializationFunction(classPointer);
This will not work unless I pass it by reference in the function declaration:
void initializationFunction(A*& classPointer);
I thought reference passing was for non-pointer type variables. I mean you don't need to pass an array by reference...
Thanks for the explanations :)
Yeah, that is true. You've to pass the argument by reference (or you can pass A** instead).
But the best solution is to write the constructor of A in such way that you wouldn't need this function in the first place. That is, whatever you're doing in this function, you should be doing that in the constructor itself.
If, however, you cannot edit the class, then you can do this instead:
A *initializationFunction()
{
A *obj = new A(.....);
//...
return obj;
}
A *classPointer = initializationFunction();
In my opinion, this approach is better than yours.
Note I didn't change the name of the function and other variables. I guess that isn't the point of the post. But I believe you would want better names for real code.
Either you declaration with the reference or the following one will do:
void initializationFunction(A** classPointer);
The point is that you are passing in a pointer argument and that you want to modify the value it had in the caller. This is an out parameter and out parameters should be passed by reference, not by value (reference here means either through a pointer or reference). This out parameter is a pointer, so you should pass a pointer to that pointer or a reference to that pointer.
In other words, you need to access the original argument in the caller stack to be able modify it. In the declaration
void initializationFunction(A* classPointer);
classPointer is akin to a local variable defined inside of initializationFunction and is just a copy of the classPointer you allocated in the caller function. Modifying a copy of classPointer will not modify the original variable, so you need a pointer to the original variable to be able to modify it. The same holds true if you use a reference to the original classPointer.
An alternative approach you have is returning the new classPointer from your function:
A* initializationFunction(void);
in this case the caller would simply do:
A* classPointer = initializationFunction();
You can pass any variable by reference. The difference between passing by reference and passing by value, is that when you pass by reference, you are in fact passing the very same pointer that is pointing to the value in that memory location, and when you pass by value you are just passing another reference to that memory location, and therefore anything you assign to it will NOT change the value of the parameter passed.
Either use a double pointer (a**) or a reference as you did.
In your first example, the pointer is passed by value (ie. the function gets a copy of the pointer). The object that the pointer points to is of course the same both in the calling code and inside the function.
In the second example, the pointer is passed by reference (ie. the function basically uses the same pointer as the calling code).
say you had a windows shortcut pointing to a text file in "My Documents".
you can copy that shortcut and paste it anywhere in windows, double click on it, and it opens the text file in "My Documents". That is passing by reference / pointer. The shortcut points to "where", then you use it to change the "stuff".
However, the code you posted doesn't "open" the file pointed to by the shortcut. It actually changes the shortcut to point to (actually create ) a new "file". But since the shortcut itself was first copied ( passed by value ), the effect is that you allocated memory but cannot access it. So analogously you changed the shortcut, created a "file", but then deleted the directory with that shortcut in there ( but your file is then lost in outer space !).
Unfortunately, there is really no analogy for passing a shortcut itself by reference, you would basically have to copy the shortcut back out of the directory, then replace the original text file in "my documents" with a shortcut to this new "file". Hope this helps instead of confuses it further :(.
The reason you have to pass the pointer by reference is that you're actually changing where in memory it points to. If you had already assigned it to an object and wanted to modify that object, passing it directly to the function would be fine.
When you do a Aptr = new A(...), you are
- Creating an 'A' object somewhere on the heap
- Assigning the address of the newly created object to Aptr
If the function doesn't have a reference to Aptr, the function can't change its value.
You can pass pointers by reference because pointers are also variables with their own address.
For example, in a 32-bit architecture, you can declare an unsigned int and use it as a pointer.
This is normal.
I explain:
void foo(X* toto)
{
toto=new X();
}
toto value will be poped out from call stack with it's initial value (as any other argument , pointer or not)
since it's not possible to change function argument value UNLESS it's a reference.
so:
void foo(X*& toto)
{
toto=new X();
}
Here you explicitely say toto argument as being X*& (X* for type , and & (reference) to let it's value be modified inside function foo)
Pointer types are the same than any other types. replace X* by int and you'll immediately find that toto won't be changed outside of function call unless passed as reference.
An X** would also have done the trick , using such implementation:
void foo(X** toto)
{
*toto=new X();
}
It should be:
void initializationFunction(A** classPointer)
{
...
...
*classPointer = new A(.....);
}
Call:
initializationFunction(&ptr);
the function will set the argument passed in to the new A(......);
example: http://ideone.com/u7z6W
I wrote a function along the lines of this:
void myFunc(myStruct *&out) {
out = new myStruct;
out->field1 = 1;
out->field2 = 2;
}
Now in a calling function, I might write something like this:
myStruct *data;
myFunc(data);
which will fill all the fields in data. If I omit the '&' in the declaration, this will not work. (Or rather, it will work only locally in the function but won't change anything in the caller)
Could someone explain to me what this '*&' actually does? It looks weird and I just can't make much sense of it.
The & symbol in a C++ variable declaration means it's a reference.
It happens to be a reference to a pointer, which explains the semantics you're seeing; the called function can change the pointer in the calling context, since it has a reference to it.
So, to reiterate, the "operative symbol" here is not *&, that combination in itself doesn't mean a whole lot. The * is part of the type myStruct *, i.e. "pointer to myStruct", and the & makes it a reference, so you'd read it as "out is a reference to a pointer to myStruct".
The original programmer could have helped, in my opinion, by writing it as:
void myFunc(myStruct * &out)
or even (not my personal style, but of course still valid):
void myFunc(myStruct* &out)
Of course, there are many other opinions about style. :)
In C and C++, & means call by reference; you allow the function to change the variable.
In this case your variable is a pointer to myStruct type. In this case the function allocates a new memory block and assigns this to your pointer 'data'.
In the past (say K&R) this had to be done by passing a pointer, in this case a pointer-to-pointer or **. The reference operator allows for more readable code, and stronger type checking.
It may be worthwhile to explain why it's not &*, but the other way around. The reason is, the declarations are built recursively, and so a reference to a pointer builds up like
& out // reference to ...
* (& out) // reference to pointer
The parentheses are dropped since they are redundant, but they may help you see the pattern. (To see why they are redundant, imagine how the thing looks in expressions, and you will notice that first the address is taken, and then dereferenced - that's the order we want and that the parentheses won't change). If you change the order, you would get
* out // pointer to ...
& (* out) // pointer to reference
Pointer to reference isn't legal. That's why the order is *&, which means "reference to pointer".
This looks like you are re-implementing a constructor!
Why not just create the appropriate constructor?
Note in C++ a struct is just like a class (it can have a constructor).
struct myStruct
{
myStruct()
:field1(1)
,field2(2)
{}
};
myStruct* data1 = new myStruct;
// or Preferably use a smart pointer
std::auto_ptr<myStruct> data2(new myStruct);
// or a normal object
myStruct data3;
In C++ it's a reference to a pointer, sort of equivalent to a pointer to pointer in C, so the argument of the function is assignable.
Like others have said, the & means you're taking a reference to the actual variable into the function as opposed to a copy of it. This means any modifications made to the variable in the function affect the original variable. This can get especially confusing when you're passing a pointer, which is already a reference to something else. In the case that your function signature looked like this
void myFunc(myStruct *out);
What would happen is that your function would be passed a copy of the pointer to work with. That means the pointer would point at the same thing, but would be a different variable. Here, any modifications made to *out (ie what out points at) would be permanent, but changes made to out (the pointer itself) would only apply inside of myFunc. With the signature like this
void myFunc(myStruct *&out);
You're declaring that the function will take a reference to the original pointer. Now any changes made to the pointer variable out will affect the original pointer that was passed in.
That being said, the line
out = new myStruct;
is modifying the pointer variable out and not *out. Whatever out used to point at is still alive and well, but now a new instance of myStruct has been created on the heap, and out has been modified to point at it.
As with most data types in C++, you can read it right-to-left and it'll make sense.
myStruct *&out
out is a reference (&) to a pointer (*) to a myStruct object. It must be a reference because you want to change what out points at (in this case, a new myStruct).
MyClass *&MyObject
Here MyObject is reference to a pointer of MyClass. So calling myFunction(MyClass *&MyObject) is call by reference, we can change MyObject which is reference to a pointer. But If we do myFunction( MyClass *MyObject) we can't change MyObject because it is call by value, It will just copy address into a temporary variable so we can change value where MyObject is Pointing but not of MyObject.
so in this case writer is first assigning a new value to out thats why call by reference is necessary.