Doubt related '&' operator in Function definition! [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Pointer vs. Reference
Hi All,
I was trying to explore and I encountered a concern with the reference operator. Consider a normal call by reference swap code as below, which works as desired
#include<iostream>
using namespace std;
void test(int *a,int *b){
int temp;
temp = *a;
*a= *b;
*b= temp;
cout<<"\n Func a="<<*a << " b=" << *b;
}
int main()
{
int a=5,b =3;
cout<<"\n Main a="<<a << " b=" << b;
test(&a,&b);
cout<<"\n Main again a="<<a << " b=" << b;
return 0;
}
On the other hand a code as below also does the same kind of swapping and yield exactly the same result.
#include<iostream>
using namespace std;
void test(int &a,int &b){
int temp;
temp = a;
a= b;
b= temp;
cout<<"\n Func a="<<a << " b=" << b;
}
int main()
{
int a=5,b =3;
cout<<"\n Main a="<<a << " b=" << b;
test(a,b);
cout<<"\n Main again a="<<a << " b=" << b;
return 0;
}
Can some one explain how different is the function call in the second example(first part I am comfortable in which the address is taken as the reference, but what happens in the second case) ?
Within the same line, hope the same happens in an assignment statement as well i.e.
int a=5;
int &b=a;
Thanks in advance.
EDIT:
Thanks for the replies. But my doubt is what exactly happens in the memory
int *pointer=&x
stores the address but what happens when we do
int &point=x.

Both versions perform an identical job and quite probably the compiler will emit identical object code.
The version using reference parameters is much easier to read.
You can pass a NULL pointer to the version that uses pointers which leads to a memory violation. The same mistake cannot be made with reference parameters.

& means that you're passing your parameter by reference. The variable you've passed is exactly the same variable you're operating in your function. Actually there is no significant difference between using pointer or reference, because when you passing pointer and then dereference it, you again get exactly the same variable. To sum up: in both cases it's possible to modify passed variable. The opposite, when you pass variables value.

In both cases you are passing the variables by reference. In the first function you can conceptually think of the address that is being passed. In the second example though, I conceptually think of the variable itself being passed, but passed by reference instead of by value.
I am not 100% sure, but I suspect on most compilers they would compile to the same object code.

Related

The address always returned is 0 instead of the actual value

Here is the simple code:
int *ad_return()
{
int a=600;
cout << &a << endl;
return &a;
}
int main()
{
cout << ad_return();
return 0;
}
The output is unexpected. The first cout prints an address that looks like a address but the cout that is in the main prints a legit 0. I couldn't find an explanation anywhere.
Based on what I have experimented, I have concluded the following:
Since the address of a local variable that has already went out of scope is undefined, it seems that gcc and g++ decided to implement a feature that sets this to zero (probably to make sure that the code segfaults instead of generating thoroughly bizarre behaviour). It does not do this in clang, but the value is undefined so both of these compilers are operating in accordance with the standard.
Try This Code.
There was problem you were trying to access address of a local variable a it is not accessible out side of the function as_return(). So declare it in global so that it is accessible to everyone.
#include<iostream>
using namespace std;
int a;
int *ad_return()
{
a=600;
cout << &a << endl;
return &a;
}
int main()
{
cout << ad_return();
return 0;
}
.
I hope you got answer

Why use pointers to swap numbers(beginner)?

I have some issues getting my head around the idea of pointers. I know what they do in theory, but i have a problem understanding what they can actually be capable of. The basic exercises that i have seen are a bit vague in my opinion because they can be done without the actual subject. For example swapping two number, either by reference or by address.
#include <iostream>
using namespace std;
int main()
{
int a = 45, b = 35;
cout << "Before Swap\n";
cout << "a = " << a << " b = " << b << "\n";
int z = a;
a = b;
b = z;
cout << "After Swap with pass by reference\n";
cout << "a = " << a << " b = " << b << "\n";
}
//copied an example i saw online with pointers and modified it to get the
same result without needing them
One example on when using pointers could be better (assuming this is some sort of school context) would be if you want to make a function to swap the numbers instead of rewriting your code a lot.
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
return
}
If you tried using integers in the function instead of pointers, it'd swap the values locally, and not swap the variables in a greater context. What you could do to achieve the same results is use references instead (ie int &a, int &b), so you don't really need to use pointers, and in this example they aren't particularly useful.
Pragmatically, std::swap()is much more useful in modern c++, but the example above might be why the online tutorial uses pointers.
Pointers can be useful in other contexts, but I don't know if that's within the scope of your question, just perhaps what the tutorial was trying to achieve by using pointers.
Use the std::swap() method for swaping.
It is more efficient.
For your understanding if we write a function which swaps two values
so we have to pass the values by reference and not by value.
same is
the case with pointers.some time we need to swap value by pointers.
So if we pass values to this function from the main it will swap it.
void swap(int&,int&);
But here it won't work if we pass values to this function from the main.
void swap(int,int);

Understanding Passing Address by Reference in C++

I wrote a simple piece of C++ code to pass addresses by reference.
I am passing the address of a variable (say y) and an array (say arr) to a class. Both arr and y will get modified inside the class. I want to have the modified values in my main().
Please find my question in the below piece of code as it is easier that way. Thanks.
#include <iostream>
using namespace std;
class A
{
public:
// Assign values to the array and increment _x.
void increment()
{
(*_x)++;
(*_arr)[0] = 1; // Q1. Is it safe to directly access the array like this.
(*_arr)[1] = 2; // Don't I have to allocate memory to the array ?
(*_arr)[2] = 3;
}
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x)
{
*_arr = arr;
}
private:
int* _x;
int** _arr;
};
int main()
{
int y = 9;
int arr[5];
int *pY = &y;
int *pArr = arr;
A *obj1 = new A(pArr, pY);
// This gives a compile time error. warning: initialization of non-const reference int *&' from rvalue `int *'
// A *obj1 = new A(&y); <-- Q2. Why does this give a Compile Time Error ?
obj1->increment();
cout << "y : " << y << endl;
cout << "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << endl;
cout << endl;
return 0;
}
In A::increment() function, I am directly assigning values to the array without
allocating memory. Is it safe to do ? If not, how can I allocate memory so that
I can still get the modified array values in main() ?
Why do I get a compile time error whey I pass &y to A's constructor ?
Thanks in advance.
Question 1
In A::increment() function, I am directly assigning values to the array without allocating memory. Is it safe to do ? If not, how can I allocate memory so that I can still get the modified array values in main() ?
Answer
Yes, it is safe.
Question 2
Why do I get a compile time error whey I pass &y to A's constructor ?
Answer
&y is not an lvalue. Hence, it cannot be used where the argument type is int*&.
Problem in posted code
*_arr = arr;
That is a problem since _arr has not been initialized to point to a valid memory. Using *_arr when _arr has not been initialized causes undefined behavior. You can change the type of _arr to:
int* _arr;
and simplify your code a little bit.
class A
{
public:
// Assign values to the array and increment _x.
void increment()
{
(*_x)++;
_arr[0] = 1; // Q1. Is it safe to directly access the array like this.
_arr[1] = 2; // Don't I have to allocate memory to the array ?
_arr[2] = 3;
}
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x),
_arr(arr)
{
}
private:
int* _x;
int* _arr;
};
without changing anything in main.
This is very rarely what you want; a T** is generally an array of arrays or else a pointer value that you want to modify in the caller’s scope. However, neither seems to be what you’re doing here.
It is safe to modify *_arr[0] if and only if _arr has been initialized to a array of non-const arrays, and (*_arr)[0] if and only if it has been initialized as a pointer to a non-const array. Neither appears to be the case here, but if it is, you probably want to give the array length explicitly.
In this example, &y is a constant. You can’t modify it, so you can’t pass it as a non-const variable. You can declare a pointer int *py = &y; and pass that. But consider whether that’s what you want to do.
By the way, it’s not good style to use identifiers that start with underscores, because by the standard, they’re reserved for the compiler to use.
You should tell us what you are trying to do. In my opinion it's nonsense using raw pointers/arrays and naked new/(missing?) delete in C++ without good reason. I would also like to note that it is not considered good practice using the _prefix for class members. Usually leading _ are used for std implementations. I recommend using m_prefix if you insist on one. And why do you give _arr the type int**? Is is supposed to be a 2D-Array? Additionally, it doesn't really make sense passing a pointer by reference. A pointer is already a pointer, if you know what I mean, just pass the pointer around.
I'm just going to assume that you are doing this to understand manual memory management or pointer arithmetics or - wait, right: Tell us what you are trying to do and why. Nevertheless, I don't understand what you have the class for:
#include <iostream>
void increment(int& x, int *arr, int sz)
{
++x;
for (int i = 0; i != sz; ++i)
{
// this just numbers the values respectively (starting at 1)
arr[i] = i + 1;
}
}
int main()
{
using namespace std;
int y = 9;
const int sz = 5;
int arr[sz];
increment(y, arr, sz);
cout << "y : " << y << '\n'
<< "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
}
To answer your questions:
2. First thing first: I don't see any constructor that only takes one argument.
Read up on "Undefined Behaviour (UB)" starting point: What are all the common undefined behaviours that a C++ programmer should know about?
I can't repeat enough that I don't understand what you are going for and that makes it hard to give solid advice.
I tried fixing your version.. well its still terrible... I highly recommend on reading up on std::array, std::vector. Maybe on pointers, C-Style Arrays and how to pass C-Style Arrays as function arguments (note: for regular C++ programming you wouldn't be doing/using that, usually).
#include <iostream>
class A {
public:
// Assign values to the array and increment m_x.
void increment()
{
++(*m_x);
m_arr[0] = 1;
m_arr[1] = 2;
m_arr[2] = 3;
}
A (int* arr, int* x):
m_x(x), m_arr(arr)
{
}
private:
int* m_x;
int* m_arr;
};
int main()
{
using namespace std;
int y = 9;
int arr[5];
A obj1(arr, &y);
obj1.increment();
cout << "y : " << y << '\n'
<< "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
A obj2(arr, &y);
obj2.increment();
cout << "y : " << y << '\n'
<< "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
}
You should also read up un pointers/references and their differences
I am actually trying to make your programming life easier. Sorry for long answer.
In answer to your first question
In A::increment() function, I am directly assigning values to the
array without allocating memory. Is it safe to do ? If not, how can I
allocate memory so that I can still get the modified array values in
main() ?
you allocated memory in main(), in the line
int arr[5];
In terms of class design, you defined your class constructor to accept reference arguments, which means that an existing int* must be passed to each argument:
A (int* &arr, int* &x)
and you do so when you invoke the constructor:
A *obj1 = new A(pArr, pY);
so in this program, what you are doing is safe. A potential danger if you expect to use this class in another context would be if your arr array in main() contained fewer than 3 elements, since your increment() function initializes the third element of the array.
In answer to your second question
Why do I get a compile time error whey I pass &y to A's constructor ?
In your original constructor,
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x)
{
*_arr = arr;
}
you are dereferencing _arr before it has been initialized. One way to solve this would be to do this:
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x)
{
_arr = new (int*);
*_arr = arr;
}
// Destructor
~A ()
{
delete _arr;
}
As an aside, you also use new in main(). Whenever you use new, you should also use delete to avoid a memory leak. So at the bottom of your program, before the return statement, add the following:
delete obj1;

C++ pointer to array return type

I have a code like that:
#include <iostream>
using std::cout;
const int ARR_SIZE=5;
int arr[ARR_SIZE];
int (*five(int first))[ARR_SIZE]
{
int result[ARR_SIZE];
for (int i=0;i!=5;++i)
{
result[i]=(i+first);
}
decltype(result) *final_arr=&result;
return final_arr;
}
template <typename T>
void print_arr(T *beg, T *end)
{
cout << "[";
for (;beg!=end;++beg)
cout << *beg << ", ";
cout << "]" << endl;
}
int main()
{
decltype(arr) *a;
for (int i=1;i!=5;++i)
{
a=five(i);
print_arr(std::begin(*a),std::end(*a));
}
return 0;
}
Basically I have a function that returns pointer to array and I would like to print the contents of this array. I would expect this code to print four arrays:
[1,2,3,4,5]
[2,3,4,5,6]
[3,4,5,6,7]
[4,5,6,7,8]
However content of the printed arrays seems random. I would be greatful for a hint on what is wrong with the code.
You are going into undefined behaviour. You return a dangling pointer in five.
int result[ARR_SIZE]; life-time is limited by scope of five, therefore it gets freed at the end. Taking its address and returning it does not prolong its life.
This decltype(result) *final_arr=&result; effectively doesn't do anything except hiding the error. You could have skipped it and write return &result; which would most probably upset compiler seriously enough to not compile the code.
Your code produces undefined behavior - returning dangling pointer from five function - it means you are returning a pointer which points to an object, which is allocated on the stack.

modifying contents of local variable of a function in a subfunction through pointer

I have the following sample code. Just wanted to know if is valid to take address of a local variable in a global pointer and then modify it's contents in a sub function. Following program correctly modifies value of variable a . Can such practice cause any issues ?
#include <iostream>
#include <vector>
using namespace std;
vector<int*> va;
void func()
{
int b ;
b = 10;
int * c = va[0];
cout << "VALUE OF C=" << *c << endl;
*c = 20;
cout << "VALUE OF C=" << *c << endl;
}
int main()
{
int a;
a = 1;
va.push_back(&a);
func();
cout << "VALUE IS= " << a << endl;
return 0;
}
This is OK, as long as you don't try to dereference va[0] after a has gone out of scope. You don't, so technically this code is fine.
That said, this whole approach may not be such a good idea because it makes code very hard to maintain.
I'd say that if your program grows you could forget about a change you made in some function and get some weird errors you didn't expect.
Your code is perfectly valid as long as you call func() while being in the scope of a. However, this is not considered to be a good practice. Consider
struct HugeStruct {
int a;
};
std::vector<HugeStruct*> va;
void print_va()
{
for (size_t i = 0; i < va.size(); i++)
std::cout<<va[i].a<<' ';
std::cout<<std:endl;
}
int main()
{
for (int i = 0; i < 4; i++) {
HugeStruct hs = {i};
va.push_back(&hs);
}
print_va(); // oups ...
}
There are 2 problems in the code above.
Don't use global variables unless absolutely necessary. Global variables violate encapsulation and may cause overlay of variable names. In most cases it's much easier to pass them to functions when needed.
The vector of pointers in this code looks awful. As you can see, I forgot that pointers became invalid as soon as I left for-loop, and print_va just printed out garbage. The simple solution could be to store objects in a vector instead of pointers. But what if I don't want HugeStruct objects to be copied again and again? It can take quite a lot of time. (Suppose that instead of one int we have a vector of million integers.) One of the solutions is to allocate HugeStructs dynamically and use vector of smart pointers: std::vector<std::shared_ptr<HugeStruct>>. This way you don't have to bother about memory management and scope. Objects will be destroyed as soon as nobody will refer to them.

Categories