|
|
a
anymore because the int object has a lifetime which is limited to the scope of the function foo()
|
|
elem
is allocated on the heap, and hence it lives also after the function call?
|
|
v[2]=23
.
|
|
T&
) to elem[2]
, and what I am doing is to set this reference to 23. Hence it's like if I would've written
|
|
elem[2]
.Why is this safe? Is this because elem is allocated on the heap, and hence it lives also after the function call? |
elem
is obviously a member variable. It's generally save to return the reference to a member variable.elem
. This is only save as long as elem
doesn't change.because now we have actually changed elem[2]. Is this correct? |
a
is a data member ?
|
|
So it seems that data member can be returned by reference independently if they're pointer or not, right? |
So, something like the following snippet (which, as can be tested, works) is allowed because a is a data member ? |
Thanks for the check(s). So it seems that data member can be returned by reference independently if they're pointer or not, right? |
From what you've shown us of your code, it looks as though the memory elem points to remains allocated for the entire life of the Vector object. |
The important thing to understand is the lifespan of the thing you're returning a reference to. |
a
? Is it safe to return a reference to it as I did in my snippet?
It is save to return the pointer as they are member variables. It is however not save to return a reference to the data pointed to. |
elem[i]
in the subscript operator, am I not returning a reference to the data pointed to?
VoB wrote: |
---|
Uhm, but since elem is a unique_ptr, then the memory will be automatically released when the Vector goes out of scope. Otherwise I should provide a destructor, but I used a unique_ptr for this precise purpose. |
For what concerns my last code snippet, now I am pretty confused: what is the lifespan of the data member a? Is it safe to return a reference to it as I did in my snippet? |
MikeyBoy wrote: |
---|
In the simpler Foo class that you posted, the reference returned by bar() is valid for as long as the Foo object exists, yes. I'd also add that there's really no point passing a primitive into the constructor as a const reference; it's no more performant than just passing the primitive by value. |
It is save to return the pointer as they are member variables. It is however not save to return a reference to the data pointed to. |
elem[i]
.MikeyBoy wrote: |
---|
If your Vector class at any point changes what elem points to, then any references you had to the old array would become useless (and, if you delete the old array, invalid). That is something I would expect to happen in a vector-like class, because one of the important features of such a container is that it manages its own memory, and re-allocates memory when required. |
elem
points to, then any reference to the old array become useless. But I think this is not true because when we implemented our Vector class, I could still access some "old" element before the push_back. So you're saying that if I push_back an integer to my vector, i.e. I am changing what elem points to, then any reference to the old array become useless. |
But I think this is not true because when we implemented our Vector class, I can access some "old" element before the push_back. |
I'm sorry for bothering you, but I can't see what I am missing. |
if your calling code is still holding onto a reference that was returned before elem got re-allocated, then it will still be referencing the old array, not the re-allocated one. |
|
|
a
is defined to be 4, and after the push_back it's still 4, because it's still referencing to the old array. I think you're referring precisely to this, right?The problem arises when you change the data pointed to. As for example you do in your move constructor/assignment. The referenced data is not longer valid after such an event. |
|
|
v
is no more available and indeed I'll get a segmentation fault. Here a is defined to be 4, and after the push_back it's still 4, because it's still referencing to the old array. I think you're referring precisely to this, right? |
|
|
|
|
200 |
a
is really a reference, as expected, because no change has been applied to v
. 3 |
a
is useless. It's interesting to me noticing that it's not invalid: possibly because the the std::vector's elem
is a smart pointer and in the reserve
function it will do something like elem.reset(tmp)
which indeed doesn't delete the old array, but just changes the location of the pointer elem and the data he's pointing to.which means that a is useless. It's interesting to me noticing that it's not invalid |