function definition in C++ [duplicate] - c++

I understand the concept of references in C++, and I understand what they do when used in function parameters, but I am still very much confused on how they work with return types.
For example, when used in parameters, this code:
int main (void) {
int foo = 42;
doit(foo);
}
void doit (int& value) {
value = 24;
}
is similar to this code:
int main (void) {
int foo = 42;
doit(&foo);
}
void doit (int* value) {
*value = 24;
}
(knowing that the compiler will automatically put an asterisk in front of value every time it is used in the first code sample of doit, but in the latter you'd have to put the asterisk in yourself every time you try to use value)
So when used as a reference what does this next code (using reference in a return type) translate to? Does it return a pointer to an int? Or would it just return an int?
int main (void) {
int* foo = /*insert useful place in memory*/;
foo = doit(foo);
}
int& doit (int* value) {
//insert useful code
}

It means you return by reference, which is, at least in this case, probably not desired. It basically means the returned value is an alias to whatever you returned from the function. Unless it's a persistent object it's illegal.
For example:
int& foo () {
static int x = 0;
return x;
}
//...
int main()
{
foo() = 2;
cout << foo();
}
would be legal and print out 2, because foo() = 2 modifies the actual value returned by foo.
However:
int& doit () {
int x = 0;
return x;
}
would be illegal (well, accessing the returned value would), because x is destroyed when the method exits, so you'd be left with a dangling reference.
Returning by reference isn't common for free functions, but it is for methods returning members. For example, in the std, the operator [] for common containers return by reference. For example, accessing a vector's elements with [i] returns an actual reference to that element, so v[i] = x actually changes that element.
Also, I hope that "is essentially equal to this code" means that they're semantically sort of (but not really) similar. Nothing more.

It means that you return a pointer to the memory address where the correspondent data is, instead of the very data.

Assuming this code (to make it comparable to the first example) :
int main (void) {
int* foo = /*insert useful place in memory*/;
*foo = doit(foo);
}
int& doit (int* value) {
*value = 24;
return *value;
}
The int& is not really useful as a return type in this case, because it provides access to the variable in memory (of which you pass the pointer to the function).
Does it return a pointer to an int? Or would it just return an int?
No, it returns a reference to an int. If you want, you can look at it as a pointer which can not be nullptr.

Hmm, the best way to know the answer is to have a try...
Your codes will not pass type check, because doit will return a reference of int while you accept the return value as a pointer of int.
You can have a look at this:
#include<iostream>
using namespace std;
int& doit (int* value) {
value[0] = 3;
return value[4];
}
int main (void) {
int* foo = new int[10];
for (int i=0; i<10; i++)
foo[i] = i;
int& bar = doit(foo);
cout<<bar<<endl;
for (int i=0; i<10; i++)
cout<<foo[i]<<" ";
cout<<endl;
bar = 12;
for (int i=0; i<10; i++)
cout<<foo[i]<<" ";
cout<<endl;
return 0;
}
The variable "bar" will accept the return value, and it can be used change the content of "foo". As is mentioned by Luchian, it maybe dangerous to return a reference from the function, because the later codes might modify a value which is in the stack.

Related

A simple question about pointer assignment in c++ function

This is my code, after a = b; in the function, a is still nullptr....
int getBox(int *a) {
int *b = new int;
*b = 3;
a = b;
std::cout << *a;
}
int main() {
int *a = nullptr;
getBox(a);
std::cout << a;
}
I guess it's a very simple problem... Maybe I forgot too much about C++
I'm not sure what you're trying to do, but this row inside the getBox():
a=&b;
Doesn't actually change a in the main, you actually overrides the pointer(the copy that was made by the function), and make it point somewhere else.
You can do something like this(again, I don't see the point) :
int getBox(int ** a){
int *b = new int;
*b=3;
*a=b;
std::cout<<*a;
}
int main(){
int *a= nullptr;
getBox(&a);
std::cout<<a;
}
Let's assume there is some type T. Now here are 3 different kinds of functions:
void f(T a) { // pass by value (this is a copy of the 'a' in main)
a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(a);
// a is still something
}
void f(T &a) { // pass by reference (this is a reference to the 'a' in main)
a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(a);
// a is now something else
}
void f(T *a) { // pass by address (this is a pointer to the address the 'a' in main)
*a = /* something else */ ;
}
int main() {
T a = /* something */ ;
f(&a);
// a is now something else
}
Now you can apply this logic to any T you want, such as int, or int*, and the same rules will work. You can try this out with getBox and see the effect of each version, which should help you understand what's going on. Note that you are using the first version (pass by value), but for the result you are expecting, you should use the second version (pass by reference).
If you really want to change what a is pointing to, then you can think it this way maybe it will help to make it a bit easier to understand. A is an int pointer and the function getBox takes a reference that you can modify its value which is an int pointer.
void getBox(int* &a) {
int *b = new int;
*b = 3;
a = b;
std::cout << *a;
}
int main(){
int *a= nullptr;
getBox(a);
std::cout<< *a;
}
This will change the value of a, which is a new pointer value to b.
Yes of course, why should changing a in getBox change the value of a in main? If you think the answer is 'because it's a pointer' then I'm afraid you've misunderstood pointers.
Look at this code
int getBox(int a){
a=3;
std::cout<<a;
}
int main(){
int a= 0;
getBox(a);
std::cout<<a;
}
Setting a=3 in getBox has no effect on a in main. Your code is exactly the same, but for some reason because pointers are involved beginners often think it works differently. It doesn't.
You can however use pointers in this way to change what is being pointed at, that's the important thing, but changing the pointer itself doesn't work in the way you are expecting.
You probably only want to change to getBox(int * & a). You then pass a reference to the pointer a to the function instead of creating a copy of the pointer that points to the same address in your case NULL.

Using pointer vector to reference vector is illegal?

I have one question.
Is it ok to use pointer vector as reference vector?
Struct Child
{
int n;
void func(int _n)
{
n = _n;
};
}
struct Parent
{
std::vector<Child> vec;
}
void func(Parent* p)
{
std::vector<Child>& ref = p->vec; // is this ok?
int value = 10;
ref[0].func(value); // is this ok?
}
int main()
{
...
...
Parent p;
func(&p);
...
...
return 0;
}
compiler gcc 4.4.7 (under c++11)
I guess, would it be okay if changed the value of the reference?
ref[0].func(value)
Thank you.
std::vector<Child>& ref = p->vec; // is this ok? yes
int value = 10;
ref->func(value); // is this ok? no
ref is not a pointer so you cannot use the member access operator ->
ref is a vector, so you need to pick which Child you want to use.
ref[ child_index ].func(value);
reference is nothing else but another name of an object. So these are all the same:
std::vector<Child>& ref = p->vec;
std::vector<Child>& vecAlias = ref;
int value = 10;
ref[0].func(value);
vecAlias[0].func(value);
p->vec[0].func(value);
You can't change a value of a reference. Uninitialized referenced don't exist. Once it's initialized there is no way of changing it.
Pointers on the other hand have similar purpose: they allow access to the same data from different places. You can always change what a pointer points to. But pointers are also more error-prone as then can be uninitialized or null-initialized. So try to stick to references if you don't need this flexibility.

SIGSEGV when trying to acces member of pointer after it was filled by function

The answer is probably stupidly easy, but I have stared at this code for quiet a while now and I simply can't find the solution.
Here is my problem. I have a pointer to a base class. Then I call a function to find an element in a vector of objects derived from that class. The pointer is passed as a parameter and filled with the found object. If I try to read a member variable of what the pointer points to I get a SIGSEV.
This is the code:
Base* control;
if(findControlByName("aName", control)) {
std::cout << control->name << std::endl; // SIGSEV happens here
}
//...
bool findControlByName(std::string name, Base* control) {
for(size_t i = 0; i < controls.size(); i++) {
if(controls[i]->name == name) {
control = controls[i];
std::cout << control->name; // this works
return true;
}
}
return false;
}
How do I do this properly?
To elaborate on my above comment, when you assign a value to a pointer parameter in a function, that value is local to the scope of the function, just like any other parameter that is passed by value. Assigning a value to the parameter in the scope of the function does not change it outside the scope of that function unless it is passed by reference.
An example:
void someFunc(int * x)
{
static int my_static = 5;
x = &my_static;
}
void someFunc2(int * &x)
{
static int my_static_2 = 7;
x = &my_static_2;
}
//somewhere else:
int * ptr;
someFunc(ptr);
//ptr is unchanged/still uninitialized
someFunc2(ptr);
//ptr points to my_static_2
If the signature of someFunc is changed to take a reference parameter, the parameter will be passed by reference instead of passed by value.

Assigning pointer to a different address in function

just curious what is the explanation of this?
void f(int * x);
int test = 100;
int main()
{
int z = 35;
int * a = &z;
f(a);
cout<<*a;
..
}
void f(int *x)
{
x = &test;
}
We are taught we can use pointers inside function arguments if we want to modify the "outside" object (as a in this case). But x = &test does not do much, and the cout still prints 35.
I know *x =someVal would work though in f().
In C pointers are passed by value just like ints, floats, etc. So if you want to modify it and have that modification be visible outside of the function call, you need to pass a pointer to the thing you want to modify, in this case that's a pointer to a int pointer:
void f(int **x) {
*x = &test;
}
However, in C++ passing a reference is a much better approach:
void f(int*& x) {
x = &test;
}
If you labeled the question C, what you taught it would be acceptable. For C++ it is techically correct but morally wrong, you should pass by reference to modify the object, not fiddling with pointer and address.
In your code you get what you coded for: pass a pointer and then reassign that poitner's value. That is not visible outside the function. What you intended to do is
void f(int *x)
{
*x = 42;
}
and the C++ version would be like:
void f(int &x)
{
x = 42;
}
int main()
{
int z = 35;
f(z);
cout << z;
}
Due to recommendation of one of the members I am adding my own answer which I derived from the other peoples responses. So thanks go to them.
Basically the problem in my code was that I was changing a copy of my pointer.
The only thing x in function f and the value a passed to f have in common is the address where they point to.

What does it mean to return a reference?

I understand the concept of references in C++, and I understand what they do when used in function parameters, but I am still very much confused on how they work with return types.
For example, when used in parameters, this code:
int main (void) {
int foo = 42;
doit(foo);
}
void doit (int& value) {
value = 24;
}
is similar to this code:
int main (void) {
int foo = 42;
doit(&foo);
}
void doit (int* value) {
*value = 24;
}
(knowing that the compiler will automatically put an asterisk in front of value every time it is used in the first code sample of doit, but in the latter you'd have to put the asterisk in yourself every time you try to use value)
So when used as a reference what does this next code (using reference in a return type) translate to? Does it return a pointer to an int? Or would it just return an int?
int main (void) {
int* foo = /*insert useful place in memory*/;
foo = doit(foo);
}
int& doit (int* value) {
//insert useful code
}
It means you return by reference, which is, at least in this case, probably not desired. It basically means the returned value is an alias to whatever you returned from the function. Unless it's a persistent object it's illegal.
For example:
int& foo () {
static int x = 0;
return x;
}
//...
int main()
{
foo() = 2;
cout << foo();
}
would be legal and print out 2, because foo() = 2 modifies the actual value returned by foo.
However:
int& doit () {
int x = 0;
return x;
}
would be illegal (well, accessing the returned value would), because x is destroyed when the method exits, so you'd be left with a dangling reference.
Returning by reference isn't common for free functions, but it is for methods returning members. For example, in the std, the operator [] for common containers return by reference. For example, accessing a vector's elements with [i] returns an actual reference to that element, so v[i] = x actually changes that element.
Also, I hope that "is essentially equal to this code" means that they're semantically sort of (but not really) similar. Nothing more.
It means that you return a pointer to the memory address where the correspondent data is, instead of the very data.
Assuming this code (to make it comparable to the first example) :
int main (void) {
int* foo = /*insert useful place in memory*/;
*foo = doit(foo);
}
int& doit (int* value) {
*value = 24;
return *value;
}
The int& is not really useful as a return type in this case, because it provides access to the variable in memory (of which you pass the pointer to the function).
Does it return a pointer to an int? Or would it just return an int?
No, it returns a reference to an int. If you want, you can look at it as a pointer which can not be nullptr.
Hmm, the best way to know the answer is to have a try...
Your codes will not pass type check, because doit will return a reference of int while you accept the return value as a pointer of int.
You can have a look at this:
#include<iostream>
using namespace std;
int& doit (int* value) {
value[0] = 3;
return value[4];
}
int main (void) {
int* foo = new int[10];
for (int i=0; i<10; i++)
foo[i] = i;
int& bar = doit(foo);
cout<<bar<<endl;
for (int i=0; i<10; i++)
cout<<foo[i]<<" ";
cout<<endl;
bar = 12;
for (int i=0; i<10; i++)
cout<<foo[i]<<" ";
cout<<endl;
return 0;
}
The variable "bar" will accept the return value, and it can be used change the content of "foo". As is mentioned by Luchian, it maybe dangerous to return a reference from the function, because the later codes might modify a value which is in the stack.