>In C++ items can be passed by reference and passed by value. This includes a short example, and some descriptions of why it works. Disclaimer: This is for my notes as I am also only learning C++.
#include <stdio.h> /* * Class that contains a couple fields for testing. */ class obj{ double z; public: //sets x to zero and points y at z. obj(){x=0; z=0; y = &z;} double x; double* y; ~obj(){ printf("destroyed %1.1f, %1.1f\n", x, z );} }; /* * Creates a copy cannot modify the original. */ void passByValue(obj o){ //doesn't propagate, because this is a copy of o, so the copies x is changed, but not //the orginals. o.x = 1; //y is a copy of the original y, but they both point to the same location. //this assignment propagates back to the original. o.y[0] = 3; } /* * Can modify the original. Special syntax. */ void passByValuePointer(obj* o){ o->x = 3; o->y[0] = 5; } /* * Similar to a pointer. */ void passByReference(obj &o){ o.x = 6; o.y[0] = 15; } int main(int arg_c, char**args){ obj o; passByValue(o); //after passing by value, we could only change the value y points at. printf("x: %1.1f y[0]: %1.1f \n", o.x, o.y[0]); passByValuePointer(&o); //after passing by value, where our value is a a pointer. printf("x: %1.1f y[0]: %1.1f \n", o.x, o.y[0]); passByReference(o); //passes a reference to our object. printf("x: %1.1f y[0]: %1.1f \n", o.x, o.y[0]); }
And the output:
destroyed 1.0, 0.0 x: 0.0 y[0]: 3.0 x: 3.0 y[0]: 5.0 x: 6.0 y[0]: 15.0 destroyed 6.0, 15.0
In the first function call, passByValue, a copy of the object is made for the function. The copy is modified. At the end of the function it goes out of scope, that is why 'destroyed 1.0, 0.0' was printed. The x value changed because we reassigned it, but the z value does not change because the pointer y* is pointing at the z value of the *original object*.
Back in main the original x was not changed because only the x of the copy was changed. The value at y[0] does change because the copy had a copy of y*, which is a pointer to the original object's z. So when we change the value that it points at, it changes the value of the original object. This behavior can be especially confusing when dealing with arrays and pointers.
double d[2]; double* e = new double[2];
'e' will behave similar to y, but assigning values to d[i] will not affect the d in the original object!
The the next two lines both demonstrate that we can modify the original object from the pointer. The fact there is only one object created is demonstrated by o dying when it goes out of scope.
Next, assignments with references and pointers. ALL OF THESE ARE POSSIBLE LEAKS.
#include <stdio.h> /* * Class that contains one field for testing. */ class obj{ public: //sets x to zero and points y at z. obj(){x=0;} double x; ~obj(){ printf("destroyed %1.1f\n", x );} }; /* * Creates an object that never gets deleted, or * propagated. This is a memory leak. */ void leakyPointer(obj* o){ o = new obj(); o->x = 1.5; } /* * Creates a new object, that replaces the original * object.The original pointer points at the new object. */ void potentialLeak(obj* o){ o[0] = * (new obj()); o->x = 5; } /* * creates a new object, which gets copied to the original * o. The created object gets deleted. */ void copiedReference(obj &o){ obj a = obj(); //o is now a copy of a. o = a; //they are midified independantly. o.x = 9; a.x = 0.33; } /* * The new object goes out of scope, and gets deleted. * The memory probably isn't reused in this example so the error might go * unnoticed. */ void leakWithReference(obj &o){ //o becomes a copy of a new object. o =* new obj(); o.x = 11; } int main(int arg_c, char**args){ obj o; o.x = 0.5; leakyPointer(&o); printf("1. x: %1.1f \n", o.x); potentialLeak(&o); printf("2. x: %1.1f \n", o.x); copiedReference(o); //passes a reference to our object. printf("3. x: %1.1f \n", o.x); leakWithReference(o); printf("4. x: %1.1f \n", o.x); }
And the output:
1. x: 0.5 2. x: 5.0 destroyed 0.3 3. x: 9.0 4. x: 11.0 destroyed 11.0
Line one, the object has not changed because we changed the value of the copy of the pointer. leakyPointer is a memory leak! Number 2. shows the object has been changed. Number 3 shows are reference allowed us to change the original object and the same with number four.
The first method does't do anything except allocate a new object on the heap and then leaves you without a reference.
The second method allocates a new object, then replaces the contents of the previous object with a new object, there are two objects now. This could be fixed by:
/* * Creates a new object, that replaces the original * object. */ void potentialLeak(obj* o){ obj* s = new obj(); o[0] = * s; delete s; o->x = 5; }
Now it is not a guaranteed leak it is only a potential leak.
The third method creates an obj on the stack, it is then copied to the original object. When the function finishes the newly created object is deleted. This is similar to the updated second method.
The last method leak with reference is the same as the potensionLead(obj* o) just using reference notation.
So the methods that do not explicitly leak, eg. copiedReference, can cause a memory leak because the existing object never gets deleted. For this example that isn't bad, but if the destructor of the object frees resources, then this could cause an issue.