Reputation: 1
I have following code
#include <iostream>
#include <vector>
using namespace std;
struct foo {
struct bar {
int foobar;
};
vector<bar*> barp;
bar & insert(int v){
bar * b = new bar();
(*b).foobar = v;
barp.push_back(b);
return *b;
}
void edit(bar & b, int v){
b.foobar = v;
}
};
int main() {
foo f;
foo::bar b = f.insert(5);
f.edit(b, 10);
std::cout << (b.foobar == 10?"true":"false") << std::endl;//now ok
std::cout << (b.foobar == 5?"true":"false") << std::endl;//now ok
std::cout << ((*f.barp[0]).foobar == 10?"true":"false") << std::endl;//after edit, still returns false
std::cout << ((*f.barp[0]).foobar == 5?"true":"false") << std::endl;//after edit, returns true
return 0;
}
Could someone explain me, why doesnt the "b.foobar" change to 10? Doesnt the b have the same address as the one saved in f.barp[0]?
EDIT:Thanks for answers, adding reference to void edit(bar & b, int v) does, of course, make sense. However adding reference to "bar & insert" doesnt seem to change anything, as the (*f.barp[0]).foobar stays unchanged after edit, even though insert should return reference now.
Upvotes: 0
Views: 64
Reputation: 2667
foo::bar b = f.insert(5);
This b object is different from *f.barp[0] since it is created from returned reference. To make this work, change this line to
foo::bar& b = f.insert(5);
That way you are creating a reference to the object which you just inserted in the vector.
Upvotes: 0
Reputation: 726489
Doesn't the
b
have the same address as the one saved inf.barp[0]
?
No, it does not. You return the object by value from the insert, i.e.
bar insert(int v)
^^^
Returning by value implies a copy: a new bar
is constructed using a copy constructor, and the original one is discarded*.
To get the results that you expect, return bar&
from insert
:
bar& insert(int v) {
// ^
}
Similarly, edit
should take its parameter by reference if you would like all functions to work on the same object.
* If it were not for you storing the pointer in a collection, this would also create a memory leak. Your program does have memory leak, too, but you can fix it by deleting objects in the barp
vector.
Upvotes: 3
Reputation: 140495
Doesnt the b have the same address as the one saved in f.barp[0]?
No, it does not. Every time you use bar
with no further qualifications as an argument or return type, you are asking for a copy to be made. In this case, that means both the variable b
in main
and the variable b
in edit
are copies.
For this toy example, you can make the program do what you expected with these changes:
- bar insert(int v){
+ bar &insert(int v){
- void edit(bar b, int v){
+ void edit(bar &b, int v){
- foo::bar b = f.insert(5);
+ foo::bar &b = f.insert(5);
If you do not understand what that does or why, please consult a C++ textbook for an explanation of "references".
(If you've never seen the above -
/+
notation before, it means "replace each line marked with a minus sign with the corresponding line marked with a plus sign.")
Upvotes: 0
Reputation: 118300
Because you're passing the parameter to edit()
by value, instead of by reference.
edit()
ends up modifying a copy of the original object, which then immediately gets thrown away.
Also, you are returning a copy of the record from insert()
, as well.
Your insert()
must return a pointer, instead of a copy of the new record. You must also pass a pointer to edit()
, too.
Upvotes: 1