Parameter passing with const primitive reference and only primitive - c++

Is there any difference between these two usage?
1.
void Foo(const double &n)
{
cout<< "Hello: " << n << endl;
}
2.
void Foo(double n)
{
cout<< "Hello: " << n <<endl;
}
I'm looking for a general answer, not only for this context. (1. usage makes me confused.)

You can't modify the value of the parameter in the first snippet, in the second one you can.
Outside the function, they both remain the same, because the second one passes by value.
void Foo(const double &n)
{
n = 3; //ERROR
}
void Foo(double n)
{
n = 3; //OK
}
For non-basic types, it makes a difference performance-wise. If you pass by reference (1.), you pass the original object, not a copy. If you pass by value, a copy is created.

If you use a reference and the value that the reference refers to changes, that change will be visible through the reference. If you pass by value, the change won't be visible. Example:
#include <iostream>
using namespace std;
double x;
void Foo1(const double& n) {
cout << n << endl;
x = 23.0;
cout << n << endl;
}
void Foo2(double n) {
cout << n << endl;
x = 23.0;
cout << n << endl;
}
int main()
{
x = 42.0;
Foo1(x); // Will print 42.0, then 23.0
x = 42.0;
Foo2(x); // Will print 42.0 twice
return 0;
}

Here is one more example that shows the difference between 'const double&' and 'double' types.
#include <iostream>
void foo1(const double &n)
{
const_cast<double&>(n) = 10.0; // <-- this code changes variable referenced by n
}
void foo2(double n)
{
const_cast<double&>(n) = 10.0; // <-- this code changes variable n
}
int main()
{
double x = 12.0;
foo1(x);
std::cout << x << std::endl; // <-- this will print '10'
x = 12.0;
foo2(x);
std::cout << x << std::endl; // <-- this will print '12'
return (0);
}
In the first case you send a reference (almost the same as pointer) to variable 'x'. In the second case you send a copy of variable 'x'.

Related

Pass reference of array of objects to function

I'm trying to change a parameter of an object inside an array, but it seems like it's creating a new one when I pass it to the function.
I already saw similar questions and answers like this one, but it doesn't work for me, because I don't have a fixed array size in the final code.
I created a very short version of the code to show the problem.
#include <iostream>
using namespace std;
class Vect {
public:
Vect(int x, int y)
{
_x = x;
_y = y;
}
int _x;
int _y;
};
void ChangeX(Vect tests[], int size)
{
for (int i = 0; i < size; i++) {
tests[i]._x = 39;
}
}
int main()
{
Vect v1 = Vect(1,2);
Vect v2 = Vect(6,3);
cout << "Initial X: ";
cout << v1._x;
cout << "\n";
Vect vectors[2] = { v1, v2 };
cout << "Final X: ";
ChangeX(vectors, 2);
cout << v1._x;
return 0;
}
I expect the output to be:
Initial X: 1
Final X: 39
But in reality is:
Initial X: 1
Final X: 1
Also, using C++ vectors is not the solution for now. I'm running low on program memory usage and have a very small space for extra code.
Your issue has nothing to do with your function. It is updating the contents of the array correctly. There is no need to pass the array itself by reference.
The real problem is with the array itself. The statement Vect vectors[2] = {v1, v2}; makes copies of the v1 and v2 objects in the array. Your function is modifying the copies, and then afterwards you output values from the originals instead of the copies. So, your output does not change, since the function is not modifying the originals.
To accomplish what you are attempting, pass in an array of pointers instead, where the pointers are pointing at the original objects, not copies of them, eg:
#include <iostream>
class Vect {
public:
Vect(int x, int y){
_x = x;
_y = y;
};
int _x;
int _y;
};
void ChangeX(Vect* tests[], int size){
for(int i = 0; i < size; i++){
tests[i]->_x = 39;
}
}
int main()
{
Vect v1(1,2);
Vect v2(6,3);
std::cout << "Initial X:\n";
std::cout << v1._x << "\n";
std::cout << v2._x << "\n";
Vect* vectors[2] = {&v1, &v2};
ChangeX(vectors, 2);
std::cout << "Final X:\n";
std::cout << v1._x << "\n";
std::cout << v2._x << "\n";
return 0;
}
Live Demo
Otherwise, start out with an array to begin with, eg:
#include <iostream>
class Vect {
public:
Vect(int x, int y){
_x = x;
_y = y;
};
int _x;
int _y;
};
void ChangeX(Vect tests[], int size){
for(int i = 0; i < size; i++){
tests[i]._x = 39;
}
}
int main()
{
Vect vectors[2] = {Vect(1,2), Vect(6,3)};
std::cout << "Initial X:\n";
std::cout << vectors[0]._x << "\n";
std::cout << vectors[1]._x << "\n";
ChangeX(vectors, 2);
std::cout << "Final X:\n";
std::cout << vectors[0]._x << "\n";
std::cout << vectors[1]._x << "\n";
return 0;
}
Live Demo

How does template in c ++ actually work in background?

**
why the output of code is
x = 1 count = 0
x = 1 count = 1
x = 1.1 count = 0
**
//code for template
#include <iostream>
using namespace std;
template <typename T>
void fun(const T&x)
{
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
int main()
{
fun<int> (1);//for int
cout << endl;
fun<int>(1);//for int
cout << endl;
fun<double>(1.1);//for int
cout << endl;
return 0;
}
Is Compiler creates a new instance of a template function for every data type in c++ in above code and also how can we assign rvalue to reference variable while calling function fun() ?
In your code, you have used the stencil to create two functions, one function uses the int type, the other function uses the double type:
void fun(const int &x)
{
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
void fun(const double &x)
{
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
The compiler can recognize the second fun<int>(1) as a call to the above integer function, thus not needing to generate a third function.
Passing by reference or const reference is the same with template functions as it is with normal functions; the template only affects the data type, not how parameters are passed.

Why cant i swap 2 numbers using static variables if static variables have only one copy stored for the whole part of the program?

If static variables has only one copy for the program. So why is it not possible to swap 2 numbers using another function?
Code:
#include <iostream>
void swap(int, int);
int main()
{
static int a = 1;
static int b = 2;
swap(a, b);
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
std::cin.get();
}
void swap(int a,int b)
{
int temp = a;
a = b;
b = temp;
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
}
As the 'swap' function is taking parameters as pass by value, copies of the variables are passed to the swap function which will only swap its local variables 'a' and 'b' (passed as parameter) not the static ones passed from main.
Swap should be taking parameters as references like below.
#include <iostream>
void swap(int&, int&);
int main()
{
static int a = 1;
static int b = 2;
swap(a, b);
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
std::cin.get();
}
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
}
Please note that static variable defined in a function pertains its value in the subsequent calls of the function in which it is declared.
This is because you are passing arguments by value and not by address(reference). Your function is working on a copy of a and a copy of b - not the original values. You could try this(notice the & in the function prototype and function definition arguments)
void swap(int &, int &);
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
}

Char pointer assignment not working

I have piece of code here.
void MyString::rm_left_space(char *s){
int size = getSize(s);
char s2[size];
char *s1=&s2[0];
int i=0;
while(*(s+i)==' '){
i++;
}
for (int k=i,l=0; k<size; k++) {//start from i, discarding spaces
*(s1+l) = *(s+k);
l++;
}
s=s1;
}
void MyString::rm_right_space(char *s){
int countSpacesfromLast=0;
int size = getSize(s);
int j=size-1;
while(*(s+j)==' '){
countSpacesfromLast++;
j--;
}
char *s2=new char[size-countSpacesfromLast];
for (int t=0; t<size-countSpacesfromLast; t++) {
*(s2+t)=*(s+t);
}
s=s2;
}
void MyString::rm_space(char *s){
rm_left_space(s);
rm_right_space(s);
}
Where there is s=s1 and s=s2 assignment does not happen. How come pointer assignment is not working.
In rm_space method s is unchanged after function calls. Why?
In rm_space method s is unchanged after function calls. Why?
Because s is passed by value. In other words - it's not the variable s that is passed but the value that s holds. The variable s in the called function and the variable s in the calling function are two different variables. Consequently, changes made to one of them does not change the other.
If you want to change s in the calling function inside the called function, you need to use call-by-reference.
Something like:
void MyString::rm_left_space(char*& s){
However, notice that your code have a major problem as it seems you are trying to assign s2 in the called function to s in the calling function. You should never do that as s2 goes out of scope as soon as the function returns.
Example: Difference between pass-by-value and between pass-by-value
This simple program uses pass-by-value
#include <iostream>
void foo(int x)
{
x = 42;
std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
int x = 21;
std::cout << "Before foo: x=" << x << std::endl;
foo(x);
std::cout << "After foo: x=" << x << std::endl;
return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=21 // notice x didn't change
because x in foo and in main are two different variables.
This simple program uses pass-by-reference
#include <iostream>
void foo(int& x) // Notice the &
{
x = 42;
std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
int x = 21;
std::cout << "Before foo: x=" << x << std::endl;
foo(x);
std::cout << "After foo: x=" << x << std::endl;
return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=42 // notice that x changed
because now x inside foo is a reference to x in main
These examples used int but exactly the same applies for pointers.
Example: Using pointers
#include <iostream>
int x = 21;
int y = 5;
void foo(int* p)
{
*p = 42;
p = &y;
std::cout << "Inside foo: p = " << p << std::endl;
std::cout << "Inside foo: *p = " << *p << std::endl;
}
int main()
{
int* p = &x;
printf("%p\n", (void*)p);
std::cout << "Before foo: p = " << p << std::endl;
std::cout << "Before foo: *p = " << *p << std::endl;
foo(p);
std::cout << "After foo : p = " << p << std::endl;
std::cout << "After foo : *p = " << *p << std::endl;
return 0;
}
Output:
Before foo: p = 0x60106c
Before foo: *p = 21
Inside foo: p = 0x601070
Inside foo: *p = 5
After foo : p = 0x60106c // Pointer value did NOT change
After foo : *p = 42 // Pointed to value DID change
Replacing
void foo(int* p)
with
void foo(int*& p)
will give:
Before foo: p = 0x60106c
Before foo: *p = 21
Inside foo: p = 0x601070
Inside foo: *p = 5
After foo : p = 0x601070 // Pointer value DID change
After foo : *p = 5 // Consequently, the pointed to value also changed
I am new to StackOverflow, if there's any mistake, please Kindly judge me
I am not sure that whether I was misunderstand what you mean, so if there's any misunderstanding, please let me know.
I guess you want to do remove left space in a string, right?
e.g.
" Hello" --> "Hello"
if so, here is my version
#include <iostream>
using namespace std;
#define SIZE 7
void rm_left_space(char* s){
int size = SIZE; //Because I don't know how to getSize, so I use fixed size instead
char s2[size];
char *s1 = &s2[0];
int i = 0;
while(*(s+i) == ' '){
i++;
}
cout << i << endl;
for (int k=i,l=0; k<size; k++) {//start from i, discarding spaces
*(s1+l) = *(s+k);
l++;
}
s=s1; // <-- Shallow copy
}
void rm_left_space_2(char* s){
int size = SIZE;
char *s2 = new char[SIZE]; <-- you should use dynamic array instead of static array
int space_num = 0;
while(*(s+space_num) == ' '){
space_num++;
}
for (int i = 0; i < SIZE; i++){
s2[i] = s[(i + space_num)%size];
}
// s = s2; // <--- shallow copy
for (int i = 0; i < SIZE; i++){ // You should copy whole array
s[i] = s2[i];
}
}
int main(){
char s[] = " hello";
cout << s << endl;
rm_left_space_2(s);
cout << s << endl;
return 0;
}
The output:
hello
hello
Also, you could check the post,
static array vs dynamic array in C++

C++ how to overload method using pass by value and pass by reference

How do I make the following overload work
#include <iostream>
using namespace std;
int subtractFive (int a)
{
a = a - 5;
return a;
}
int subtractFive (int &a)
{
a = a -5;
return a -5;
}
int main()
{
int A = 10;
cout << "Answer: " << subtractFive(*A) << endl;
cout << "A Value "<< A << endl;
cout << "Answer: " << subtractFive(A) << endl;
cout << "A Value "<< A << endl;
return 0;
}
Tried but doesnt compile
#include <iostream>
using namespace std;
int subtractFive (int a)
{
a = a - 5;
return a;
}
void subtractFive (int* a)
{
*a = *a -5;
}
int main()
{
int A = 10;
cout << "Answer: " << subtractFive(A) << endl;
cout << "A Value "<< A << endl;
subtractFive(A);
cout << "A Value "<< A << endl;
return 0;
}
You might try specifying an overload that takes an address as an argument:
int subtractFive (int *a)
{
*a = *a -5;
return *a -5;
}
Declare one function as pass by address the other by value or reference:
void subtractByFive(int * p_value)
{
if (p_value != NULL)
{
*p_value -= 5;
}
return;
}
A value and a reference have the same type so you can't overload on it. If you want two functions one of which modifies its parameter and one that returns the new value then you either have to give them different names or different types (e.g. make the latter function use a pointer type).