This question already has answers here:
Pass by reference and value in C++
(5 answers)
Closed 5 years ago.
I wrote the folloing code to test how to change values of class object in a function.
using namespace std;
class test{
public:
int a;
};
void runer(test testXX){
testXX.a=10;
}
int main()
{
test test1;
test1.a=5;
runer(test1);
cout<<test1.a;
return 0;
}
When I run the following code the output is 5 and not 10. Is it because I can't change the values of class instances, like I can't change the values of array members without using pointers? I would be grateful if someone could clarify that!
void runer(test testXX){
testXX.a=10;
}
Takes a full copy of the type test, so it is modified in the function, but a different instance to the one in main.
Parameters in C++ are sent by value. The simplest example which makes sense is
int function( int value ) {
for( ; value > 0 ; value-- ){
cout << "Hello\n";
}
}
int main( int , char ** ){
int value = 10;
function( value ); // display 10 things
function( value ); // display 10 things again (not modified).
function( 5 ); // also not making sense, if parameter is modified.
}
To allow objects to be modified, they need to be sent as references, or pointers. This allows the value of the item to be changed. The literal 5 can not be sent to a function expecting a reference.
void runer(test & testXX){
testXX.a=10;
}
Now the same object is sent from main to runner, and modifications are done to the single object.
You are passing the argument to the function by value, so it gets a local copy that only lives as long as the scope of the function.
If you want the function to be able to modify the original object that you pass in, then pass it by non-const reference void runer(test& testXX) .
Your code makes a call by value. Hence, the change doesn't appear in the actual object. To change the value of the attribute of the object you need to make a call by reference.
void runer(test &t){
t.a = 10;
}
Related
In the following call-by-value example, I cannot understand why this code is not changing the value of the 5 to a 6.
Line 11 calls the function changeValue which has the value 6, so I would have thought 6 should be output, however 5 is still output?
#include <iostream>
using namespace std;
void changeValue(int value);
int main()
{
int value = 5;
changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
void changeValue(int value)
{
value = 6;
}
// This doesn't change the value from 5 to 6. 5 is output?
When you pass a function argument by value a copy of the object gets passed to the function and not the original object.Unless you specify explicitly arguments to functions are always passed by value in C/C++.
Your function:
void changeValue(int value)
receives the argument by value, in short a copy of value in main() is created and passed to the function, the function operates on that value and not the value in main().
If you want to modify the original then you need to use pass by reference.
void changeValue(int &value)
Now a reference(alias) to the original value is passed to the function and function operates on it, thus reflecting back the changes in main().
The value of value isn't changing because your int that you pass to the function is being copied into the stack frame of the function, then it's being changed, and when the function exits the copy is destroyed. The original in main's stackframe has not changed, since it was copied to the changeValue.
If you want to change it, you should pass a reference to an int, like so void changeValue(int& value), which says that the value isn't copied into the function, but merely an alias to the original is passed.
The behavior being observed currently is because passing by value means a copy of value (new integer with value of value) is actually passed to the function.
You have to pass by reference. For that the changeValue function will look like this:
void changeValue(int& value)
Rest of the code will remain the same.
Passing a variable by reference means the same int value declared in main is passed to the changeValue function.
Alternatively, you can pass a pointer to value to the changeValue function. That will however, require changes to how you call the function also.
int main()
{
int value = 5;
changeValue(&value);
...
return 0;
}
void changeValue(int* value)
{
*value = 6;
}
I'm including this answer as another way to think about writing functions and passing parameters by value.
You could also have written this code in the following way. That is pass the parameter by value, modify the local copy in the function, which does not alter the original value, and return the altered value.
int changeValue(int val)
{
val = 6;
return val;
}
int main()
{
int value = 5;
value = changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
I am not in any way indicating my suggestion for your program is better than passing by reference. Instead, it is just the way learning a functional programming language (Clojure) is affecting the way I think.
Also, in languages like Python, you cannot modify a scalar parameter. You can only return a new value. So my answer is more of an exercise in thinking about things differently in C/C++.
AND:
the copy is assigned 6, but the change is not returned.
you need some reference or pointer if you want to change the value:
try using a method signature like:
void changeValue(int& value)
that will probably do what you expected
This is because the change in the changeValue () function is local. When you can changeValue (value) the contents of the variable value in main is copied in the formal argument named value (same name) of the function. Same name does not mean that the both are same. The value you are accessing inside the function is a copy of the value you had in the main.
To change you either need to pass it by reference or a pointer
void changeValue (int *val)
{
*val = 6;
}
call with changeValue (&value) in main
This works because the address of the variable value in main is passed and this address value is copied into val of the function. By doing *val we can get the contents of the address which was copied into val, which in actually the contents of value in main.
OR
void changeValue (int &val)
{
val = 6;
}
I have an int member named size within my blob class whose value I am attempting to change within a method. Initially, I tried...
void blob::make_union(blob parent_blob){
parent=&parent_blob;
parent_blob.size = parent_size
}
Then I tried making a function whose sole purpose was to change the size value. Its worth noting that it changes the values within the function as verified by some cout statements.
int blob::change_size(int dat_size){
size=size+dat_size;
return this.size;
}
after making the new method change my other method
'void blob::make_union(blob parent_blob){
parent=&parent_blob;
int temp = size;
parent_blob.size = parent_blob.change_size(temp);
}'
still no dice. The following within main function does work.
if (charmatrix[m-1][n-1]==charmatrix[m][n]){
blobmatrix[m][n].make_union(blobmatrix[m-1][n-1]);
blobmatrix[m-1][n-1].size=blobmatrix[m-1][n-1].size + blobmatrix[m][n].size;
What am I doing wrong?
You are passing your blob class by value: you are making a copy of your blob object, and that is what the function change_size is working with.
void increment_number(int i) { ++i; }
void increment_number_ref(int& i) { ++i; }
int main()
{
int n = 6;
// This takes a copy of the number, and increments that number, not the one passed in!
increment_number(n);
// n == 6
// This passed our object by reference. No copy is made, so the function works with the correct object.
increment_number_ref(n);
// n == 7
return 0;
}
You need to pass your blob by reference (or as a pointer) if you wish to modify that object's value: see above.
In languages that have pass by reference and pass by value - if you have a situation where you make a change, and then suddenly the change is 'gone', you're almost certainly passing a copy vs a reference.
Try changing the prototype to pass in the blob by reference.
I have a shape class that I initialize from my main program and give the parameters in the constructor.
Shape *cusomShape = new CustomShape(float radius, float origin)
The shape class has some functions such as rollover and more.
When the rollover function inside the shape class is fired, I want to change a certain int value in the main program. This might similar to firing of an event that changes the value when the rollover function is fired, but I am not sure how to do that in C++. If at all, events is the ideal approach here, it would great to see a short example coming.
If using the event is not the correct, what would the ideal way to go about this?
I think what you need is to pass a value by pointer or reference to the function in Shape and then modify it. If the function is called not from main but from somewhere else passing the pointer is the better option you have. First pass the pointer to the class and store it using another method and then each time rollover is called make use of it.
EDIT: example:
class CustomShape {
void storePointer(int* _value) {
value = _value;
}
void rollover() {
.. do stuff
*value++; // for instance
... do stuff
}
int * value;
}
int main() {
int a;
CustomShape cs;
cs.storePointer(&a);
....
cs.rollover();
....
return 0;
}
Pass a reference to the variable in the constructor and save that reference. Change the value when needed.
I would suggest passing a reference to the variable to the member function that needs to change its value. Storing a reference in a class couples the Shape class to the reference. This means that each time you want to use the Shape, without updating the integer, you cannot, since the Shape constructor will expect a reference/pointer to the int as an argument (the Shape class will store the pointer/reference as an attribute). Passing a reference/pointer to the member function promotes Low Coupling.
#include <iostream>
class Shape
{
double shapeValue_;
public:
Shape (double value)
:
shapeValue_(value)
{}
void fireFunction(int& updateMe)
{
updateMe = 123;
}
};
using namespace std;
int main()
{
int update;
cout << update << endl;
Shape s(4.5);
s.fireFunction(update);
cout << update << endl;
return 0;
};
And in this case, you have an option for a main program that doesn't involve shape object calling on fireFunction:
int main()
{
Shape s(4.5);
// Main program that doesn't use fireFunction.
return 0;
};
In this case, if you have member functions changing input arguments, you should take on a style for defining such functions: e.g. make sure that the variable that gets changed by the member function is always the first input argument in its declaration.
If you want complex objects to communicate updates between each other, you can make use of the Observer Pattern.
I have a thread-class Buffer (own made class), and many derived classes such as BufferTypeA, BufferTypeB...
Since I have to synchronize them in a certain order, I'm giving any of them an integer which represents the order to run certain task. I also have to know inside each thread Buffer which one is next to run the task, so I'm passing every BufferType a reference to an integer which all of them must share and I didn't want to make it Global.
I got lost at any point and I don't see where.
First I create all the BufferTypes from a class where I also define that shared integer as:
int currentThreadOrder;
And when creating the BufferTypes:
int position = 0;
if (NULL == bufferA) {
bufferA = new BufferTypeA(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferB) {
bufferB = new BufferPos(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferC) {
bufferC = new BufferRtk(¤tThreadOrder, ++position,
waitCondition);
}
Then, in BufferTypeA header:
class BufferTypeA: public Buffer {
public:
BufferTypeA(int currentThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//..
}
And in cpp file:
BufferTypeA::BufferTypeA(int currentThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition):
Buffer(currentThreadOrder, threadConnectionOrder, waitCondition) { }
Now I'll show Buffer header:
class Buffer: public QThread {
public:
Buffer(int ¤tThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//...
protected:
QWaitCondition *waitCondition;
int threadConnectionOrder;
int ¤tThreadOrder; // Shared address
}
And finally the cpp:
Buffer::Buffer(int ¤tThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition) {
this->threadConnectionOrder = threadConnectionOrder;
this->waitCondition = waitCondition;
this->currentThreadOrder = currentThreadOrder;
}
And the error I'm getting is error: uninitialized reference member Buffer::currentThreadOrder.
I'm embarrased to ask, because it's going to be a simple problem with pointers and addresses, but I can't see where the problem is, so please help.
When you create a class with a data-member that is a reference, the reference needs to be assigned a value in the constructor initializer list.
References have to be given a value when they are created, they are not pointers. They have to start with a value and that value cannot be changed (while the contents that is pointed to by that value can be changed).
Essentially you can think of a reference as an alias for an existing variable. You can't give a friend a nickname if you don't have a friend :)
RESPONSE TO COMMENT:
You don't "share a reference" between objects. Each object will have its own reference to the same variable. When you "pass by reference" you are telling the compiler that you want the variable in your function to actually be the variable in your outer scope, rather than creating a new variable by value. This means that you only have one variable at one memory location. The reference is just memory in some other place that forwards you to that same memory location.
Think of this as call forwarding... I can have 15 phone numbers in 15 different countries. I can set them all up to forward calls to my cell in the US. So, people are calling me no matter which number they call.
Each of your classes just has another reference to forward the "phone calls" or variable reads/writes to that same memory location. So, you're not sharing a reference between classes, you're making sure that each class HAS a reference to the same underlying memory location.
Back to the metaphore, each class won't have the same phone, but each class' phone will forward to the same number (variable) none-the-less which lets them all set/get the same value in the end.
RESPONSE II:
Here's a simple example to get your head going, it's pretty easy to apply to your classes. I didn't compile it but it should work minus a typo or two possibly.
class A
{
public:
A(int& shared) : m_shared(shared)
{
//No actions needed, initializer list initializes
//reference above. We'll just increment the variable
//so you can see it's shared in main.
m_shared += 7;
}
void DoSomethingWithIt()
{
//Will always reflect value in main no matter which object
//we are talking about.
std::cout << m_shared << std::endl;
}
private:
//Reference variable, must be initialized in
//initializer list of constructor or you'll get the same
//compiler error again.
int& m_shared;
};
int main()
{
int my_shared_integer = 0;
//Create two A instances that share my_shared_integer.
//Both A's will initialize their internal reference to
//my_shared_integer as they will take it into their
//constructors "by reference" (see & in constructor
//signature) and save it in their initializer list.
A myFirstA(my_shared_integer);
A mySecondA(my_shared_integer);
//Prints 14 as both A's incremented it by 7 in constructors.
std::cout << my_shared_integer << std::endl;
}
you pass a pointer int* as 1st argument to BufferTypeA, which expects and int, while you said in your question you meant to use a int&. To do this, the ctor of BufferTypeA should take a int& and initialise it in an initialisation list (i.e. not within the { } part of the ctor) like
class BufferType {
int &Ref;
public:
BufferTypeA(int& ref) : Ref(ref) { /* ... */ }
};
and in your construction of BufferA you must not pass an address, but the reference, i.e.
int counter;
Buffer = new BufferType(counter);
You want code like this:
Buffer::Buffer(
int ¤tThreadOrder0,
const int threadConnectionOrder0,
QWaitCondition *const waitCondition0
) :
threadConnectionOrder(threadConnectionOrder0),
waitCondition(waitCondition0),
currentThreadOrder(currentThreadOrder0)
{}
The reason is related to the reason you cannot write
const double pi;
pi = 3.14;
but can write
const double pi = 3.14;
A reference is typically implemented as a constant pointer, to which one cannot assign an address after one has initialized the pointer. Your version of the code assigns, as in the first pi example. My version of the code initializes, as in the second pi example.
So I'm still rather new to programming/C++, and still trying to wrap my head around pointers and passing by reference and everything. A program I'm trying to figure out now needs to pass an array of structs to another function. I've gotten it working by just passing the array directly there. It seems to work fine. However, what I'm concerned about is that I believe I'm passing it by value, and I understand that it's better to pass structs by reference, so you're not making a copy of the struct every time...
Anyway, here's a basic example of what I'm doing:
struct GoldenHelmet {
int foo;
string bar;
};
void pass (GoldenHelmet ofMambrino[], int size);
int main () {
GoldenHelmet ofMambrino[10];
int size = sizeof(ofMambrino) / sizeof(ofMambrino[0]);
ofMambrino[1].foo = 1;
pass(ofMambrino, size);
cout << ofMambrino[2].foo << endl;
return 0;
}
void pass (GoldenHelmet ofMambrino[], int size) {
ofMambrino[2].foo = 100;
ofMambrino[2].bar = "Blargh";
}
From what I understand, it works because arrays are already pointers, right? But the way I have that configured, am I still passing a copy of the struct and everything to the pass() function? I've tried to pass it by reference, but it doesn't seem to want to work any way I've tried.
The C++ way:
#include <array>
typedef std::array<GoldenHelmet, 10> Helmets;
void pass(Helmets &);
int main()
{
Helmets h;
h[1].foo = 1;
pass(h);
//...
}
void pass(Helmets & h)
{
h[2].foo = 100;
// ...
}
Indeed, we pass the array by reference.
This syntax:
void pass (GoldenHelmet ofMambrino[], int size)
is actually quite confusing. Because you are not passing an array, you are passing a pointer. They are not the same thing though, don't get confused. This oddity only applies to function parameters. The above is exactly identical to this:
void pass (GoldenHelmet * ofMambrino, int size)
It's actually impossible to pass an array by value, unless it is a sub-object of another object. You can pass them by reference, you need to include the size though, but you can do that using a template:
template<int N>
void pass (GoldenHelmet (&ofMambrino)[N])
These are all possible, but none of them are pass by value. Just think of ofMambrino as being the address of the beginning of the array, and that is what you are passing.
void pass (GoldenHelmet ofMambrino[], int size)
void pass (GoldenHelmet ofMambrino[10], int size)
void pass (GoldenHelmet *ofMambrino, int size)
void pass (GoldenHelmet (&ofMambrino)[10], int size)
Arrays are represented and passed as pointers, so you are not copying anything here. In contrast, if you were passing a single struct, it would be passed by value.
Below is a code snippet to illustrate this last point:
void passByVal (GoldenHelmet ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}
void passByRef (GoldenHelmet& ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}
int main() {
GoldenHelmet h;
passByVal(h); // h does not change
passByRef(h); // fields of h get assigned in the call
}
First of all array is not pointers. We refer this as a pointer in the argument list because when we use
int x[ ]
x is actually const pointer that points the beginning of the array. And when you pass this to a function you send the adress of the memory that is beginning of the array. Thats why when you make a change in your function, you make change in the adress of your variable in the caller section actually. This is actualy simulated call by reference not call by reference. But effect is same with call by reference because you are working on memory locations. For this reason when you send array of your struct you pass actually adress of your array of structs. Thats why when you change value on this, you actually change your structs.
To use call by reference, one thing you must to do is to define your function prototype like
void f(int ¶m)
and when calling function, it is same with the others.
To summarize:
int main()
{
int x;
// simulated call by reference that use adress of variable,
// lets say adress of x is 19ff
f(&x); // actually you send 19ff
f(x); // call by reference that use reference of variable
}
// simulated call by reference
void f(const int *y)
{
// when you use like *y=10, you are writing on memory area 19ff, you actually
// change memory area that is belong to x in the main
}
// call by reference
void f(const int &y)
{
}