Reference Reassignment - c++

I have a general C++ question.
Lets say I have this code:
int& GetInt()
{
int* num = new int();
return *num;
}
int numCopy = GetInt();
In this situation, what happens to the returned reference? This example uses a simple data structure so it doesn't really matter, but in cases where the returned data is more complex, would assigning a variable to a heap-allocated variable reference like this copy the data over to numCopy completely, or would numCopy become another reference to the original num?

In this situation, what happens to the returned reference?
It goes out of scope at the end of the full expression and you have now leaked the memory you acquired in GetInt. You've made a copy of the value the reference refers to, but the original object, and the memory it occupies are no longer accessible.
If you had
int& foo = GetInt();
then you could later on do
delete &foo;
to not have a memory leak, but this is still bad practice.
or would numCopy become another reference to the original num?
You only ever get a reference if you specifically ask for it.
int numCopy = GetInt();
says numCopy is an int, not a int&, so it will not be a reference. C++ has what is called value semantics, which basically means unless you ask for a reference, the object you create is it's own object that is independent from all other objects.

Related

pointers scope questions and return reference of pointer inside vector of pointers encapsulated in class

I have some questions about pointers, scopes and pointers inside vector encapsulated in class
i have this supposed cases and examples with questions:
Example 1
the variable int y scope is inside the function and when the function finish and go away that returning reference will be died and that reference be referenced to nothing?
int& createInt() {
int y = 5;
return y;
}
case1: if i do this in main or other function:
int x = createInt();
std::cout << "x value \n";
std::cout << x << "\n";
// std::cout return 5
this mean that im saving my own copy of the value of createInt()
function that is 5 in the variable x, so is safe because int x contain their own value?
but what happen with the reference returning from the createInt() function, is there a memory leak or not because is not a pointer a will die with the scope of the function.
case 2: if i do this in main or other function:
int &x = createInt();
std::cout << "x value \n";
std::cout << x << "\n";
// std::cout return 32767
int &x is equals to the reference returning from createInt() function, that reference die when the function finish/go away so for that reason
int &x is returning a wrong value 32767 and not 5 or what are that 32767 value?
so int &x = createInt(); is evil and very bad practice because is reference to nothing.
example 2
what about this? i'm requesting allocation memory for int and initialized memory to the pointer variable...
int& createInt() {
int* y = new int(5);
return *y;
}
that pointer variable is in the stack but store a reference to the new int that is in the heap, so that new int will be alive when the scope of the function go away because is in the heap right?
so when i return the reference i'm returning the reference to that new int not the pointer variable, right? so is bad to returning the reference instead of the pointer? for what?
case1: if i do this in main or other function:
int x = createInt();
std::cout << "x value \n";
std::cout << x << "\n";
// std::cout return 5
i'm creating a copy of the new int value from createInt() in my local int x variable, so is this a memory leak because i'm creating a copy and not getting the pointer, so i can't do a delete of int x variable because is not a pointer, and also i can't delete the int *y pointer created inside createInt() function because the pointer is lost, i don't have it outside the createInt()
but whats happen if i do:
delete &x;
i will get a error:
malloc: *** error for object 0x7ffee204b8c8: pointer being freed was not allocated
because i'm deleting my int x that is not in the heap? or is trying to delete the int *y inside the createInt() function ?
case2: if i do this with the same function:
int &x = createInt2();
std::cout << "x value \n";
std::cout << x << "\n";
// std::cout return 5
my int &x is a reference of the returning by createInt()
so i can do:
delete &x;
is a memory leak here? but its so bad delete &x reference instead of the pointer int *y? maybe doing delete & i'm not have form to be sure if that is allocated memory or is stack memory, so good practice is never try to delete using &?
vectors parts:
i have a class A that contain a vector of pointers of class B, also i have a method that return a element of the vector but as reference (because i want to have it in memory to reutilize it and control when is deleted like a connection pool also i move it from used vector to notInUsevector but this is other history), and in the destructor of class A i delete all the vector elements:
Class A {
//this is singleton
public:
static A& getInstance()
{
std::call_once(m_once, []() {
instance.reset(new Database());
});
return *instance;
}
B& getFirstElement() {
auto element = connections.front();
return *element;
}
~A() {
for(auto element : myVector){
delete num;
}
}
A(A const &) = delete;
void operator=(A const &) = delete;
private:
A();
static std::unique_ptr<A> instance;
static std::once_flag m_once;
std::vector<B*> myVector;
}
so in other place/function/class etc i do:
auto element = &A::getInstance().getFirstElement();
or maybe is best or the same:
auto &element = A::getInstance().getFirstElement();
so when the Class A instance is deleted the destructor will delete all the pointers inside myVector
is this safe, there is a memory leak? it's a very bad return the reference in the getInstance() function instead of the pointer?
thanks
First of all let's make it clear, scope is "layer" between { and }. It might be a function body, statement (if, switch, for, etc.) or standalone scope. The most important consequence is that life time of objects created on stack is limited to that scope.
Take your function createInt() as example, internal int y, exists only inside of that function. The moment you reach } that memory is free.
Second thing is term memory leak. Memory leak is a situation where you have a chunk of memory (might be a single byte, might be a couple of pages) and no way to point at it. It's like a locked box without a key. It is there, it is yours memory, it won't be free unless you tell, problem is you don't know where that memory is located, you have no pointer for it.
That's being said, let's talk about your cases:
Example 1 Case 1:
You are lucky. Your function return its internal y by reference, but this returned variable is freed before you return from your function. Effectively you have a value written down on sticky note, then you throw it to the trash and then return saying that your value is on that note that is in trash. The only reason you can still read it is because no one assigned that bit of memory in the mean time and it was not overwritten. Remember, the moment your function reached } all stack alocated variables (y was allocated on stack) are destroyed. That also answer your second question about memory leak, there is no memory leak. As long as you work with stack, allocation and deallocation is done "automagically" as destructor calls are inserted at the end of the scope (usually) by compiler.
Example 1 Case 2:
The very same thing as in case 1. Your returned value is compromised because you returned stack allocated variable that is no longer valid as you return from function. Now you can observe this because between assigning and reading that value you make a function call. Depending on where original y was allocated that bit of memory might be reused during std::cout call. This become obvious as you work on the very same bit of memory cause of reference usage. Remember when you reached } of createInt(), you free that bit of memory. As an additional excersise, put a break point on lines int &x = createInt(); and int x = createInt(); then step into function and watch memory state as you leave it.
Example 2 Case 1:
Now you create (potential) memory leak. You allocate a memory on heap so it won't be destroyed as you leave function body. You also pass that exact memory address, so you also should take responsibility for freeing it and you don't call delete, so that's your memory leak. And one more problem occurs as you assign returned value to completely new stack allocated variable. Your original x from createInt() is allocated, then returned by reference but feed to assign operator to other independent variable (int x have different address than int* y). Again you can check this with help of breakpoints and debugger.
Example 2 Case 2:
Now this is almost proper use of variables returned by reference and assignment of them. You create variable x on heap, then return it's address and assign it to y. Problem being as x was created on stack you are responsible for destroying it so call to delete is neccessary to avoid memory leak. Put a break point and track memory addresses of both x and y. They are the same.
General rule of thumb is that return by reference should be used only with variables that exist outside of function, for example you can use it for class memebrs as they live inside the object or for global or static variables. For other purposes use return by value, unless you really need that very object, then return it by pointer. And while you work with pointers always be aware that someone at some point have to delete underlying variable.
I skip the part about vectors and instead point you a good tool for tracking memory leaks. It's not the best solution by any means, but for starters it will do the trick (assuming you are using Visual Studio).
https://learn.microsoft.com/pl-pl/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2019
Remember to use breakpoints and debugger instead of printing everything to output/console. This will help you a lot. In both tracking memory and variable state, and understanding what your code really does.
I don't have the impression you have a real question at all, because you seem yo have found out all tricks, traps and good practices on your own. You seem to know about memory leaks and dangling references. Static and dynamic allocation. Most of your assumptions seem correct. Some hints though :
* references '&' and raw pointers result in exactly the same machine instructions, but they are hints to the programmers. Indeed, a method returning a reference likely means you don't have to take ownership for that reference, but without documentation there is no guarantee on the lifetime of that object. A raw pointer may represent a heap instance, or an optional argument, but it could also represent just a reference. This lack of ownership rules in C/C++ is indeed tricky.
* When dereferencing a dangling reference, the behavior is undefined. It may be working perfectly on your machine and it could burn my harddisk. Anything goes.
* When dealing with heap allocations, we nowadays prefer yo use smart pointers whenever possible. There is no mistaking in it's usage. Search for unique_ptr and shared_ptr
* Finally I recomy learning a bit of Rust. This is a programming language that was specifically designed to resolve such object lifetime/ownership issues. It is quite easy to install and run the most basic examples. Just try returning a dangling reference with Rust, you'll learn a lot, believe me.

Hold a unique pointer reference to a unique pointer reference

Here is a program that represents my conceptual problem:
int main()
{
unique_ptr<int> a = make_unique(5);
{
unique_ptr<int>& b = a;
}
printf("%d",*a);
}
Is a the owner of the object?
When a goes out of scope, does the value of somepointer get destroyed?
By running the above code I see it doesn't but I don't understand why. What exactly happens in the assignment?
a remains the owner of the object this entire time.
In C++, placing & before a variable name creates a reference, which is like an implicit pointer. Since you've declared b as a reference, there is only ever one unique_pointer in this code. a is the unique_pointer itself, and the reference b points to that pointer.
This is the reason the unique_pointer is not destroyed when the block containing b is exited; b never owned the resource because b was never a unique_pointer to begin with, only a reference to one.
See learncpp for a full lesson on references.
The assignment to b is simply a reference, it has no bearing on the object lifetime of a. Imagine instead that you had passed a to a function taking a unique_ptr<int> &, you wouldn't expect the reference to alter the lifetime of a in that case, why would you do so here?

c++ taking the address of a temporary object [duplicate]

This question already has answers here:
Taking the address of a temporary object
(7 answers)
Closed 7 years ago.
I have two code segments which I expected the same outcome:
First one:
SomeClass somefunc(...){
SomeClass newObj;
//some codes modify this object
return newObj;
}
int main(){
SomeClass *p;
p = &(somefuc(...));
}
Second one:
SomeClass *somefunc(...){
SomeClass newObj;
//some codes modify this object
return &newObj;
}
int main(){
SomeClass *p;
p = somefunc(...);
}
Why is it I got a "taking the address of a temporary object" error when I tried to build the first code segment, while the second code segment doesn't produce an error?
Before you even think about this, you need to learn the rules of temporary lifetime.
The broad case is that a temporary object is destroyed at the end of the full-expression creating it. The implication is that if
SomeClass *p;
p = &(somefunc(...));
were allowed to work, p would be a dangling pointer, targeting an object that no longer exists.
The big exception to the above rule is that when a reference with automatic lifetime is directly bound to the temporary object, the lifetime of the temporary is extended to be equal to the lifetime of the reference. Note that this does not cover const T& make_lvalue(const T& t) { return t; } because the reference isn't binding directly, nor class member references.
There are a few cases which are completely safe, in which the address of the temporary is only used immediately and not stored for later. e.g.
memcpy(buffer, &f(), sizeof(decltype(f())));
Of course, this results in the "address of a temporary" error you're encountered, but you can work around it via
memcpy(buffer, std::addressof(f()), sizeof(decltype(f())));
But do NOT store the resulting pointer.
The first snippet does rightfully not compile because, as the compiler said, you cannot take the address of a temporary object because it would be destroyed at the end of the expression (here: the assignment). Thus, saving its address would be meaningless.
The second snippet does compile, but is still incorrect although it might seem to work for the reasons stated here (at least if you try to access the object through the pointer).
The first example does not compile because somefunc returns a value, and you attempt to take the address of this temporary thing it returns. This would work:
Someclass* p;
Someclass val = somefunc (...);
p = &val;
The second example does not compile -- or shouldn't -- because somefunc is supposed to return a Someclass, but instead it returns a pointer to a Someclass. Make it return Someclass* and then it should compile -- but now you're returning a pointer to a local variable, which no longer exists after you leave the function. Best solution is the first example, as patched here.

Return by reference in C++ - Reference assignment vs value assignment

Suppose I have:
class SomeObject {
};
SomeObject& f() {
SomeObject *s = new SomeObject();
return *s;
}
// Variant 1
int main() {
SomeObject& s = f();
// Do something with s
}
// Variant 2
int main() {
SomeObject s = f();
// Do something with s
}
Is there any difference between the first variant and the second? any cases I would use one over the other?
Edit: One more question, what does s contain in both cases?
First, you never want to return a reference to an object which
was dynamically allocated in the function. This is a memory
leak waiting to happen.
Beyond that, it depends on the semantics of the object, and what
you are doing. Using the reference (variant 1) allows
modification of the object it refers to, so that some other
function will see the modified value. Declaring a value
(variant 2) means that you have your own local copy, and any
modifications, etc. will be to it, and not to the object
referred to in the function return.
Typically, if a function returns a reference to a non-const,
it's because it expects the value to be modified; a typical
example would be something like std::vector<>::operator[],
where an expression like:
v[i] = 42;
is expected to modify the element in the vector. If this is
not the case, then the function should return a value, not
a reference (and you should almost never use such a function to
initialize a local reference). And of course, this only makes
sense if you return a reference to something that is accessible
elsewhere; either a global variable or (far more likely) data
owned by the class of which the function is a member.
In the first variant you attach a reference directly to a dynamically allocated object. This is a rather unorthodox way to own dynamic memory (a pointer would be better suited for that purpose), but still it gives you the opportunity to properly deallocate that object. I.e. at the end of your first main you can do
delete &s;
In the second variant you lose the reference, i.e. you lose the only link to that dynamically allocated object. The object becomes a memory leak.
Again, owning a dynamically allocated object through a reference does not strike me as a good practice. It is usually better to use a pointer or a smart pointer for that purpose. For that reason, both of your variants are flawed, even though the first one is formally redeemable.
Variant 1 will copy the address of the object and will be fast
Variant 2 will copy the whole object and will be slow (as already pointed out in Variant2 you cant delete the object which you created by calling new)
for the edit: Both f contain the same Object
None of the two options you asked about is very good. In this particular case you should use shared_ptr or unique_ptr, or auto_ptr if you use older C++ compilers, and change the function so it returns pointer, not reference. Another good option is returning the object by value, especially if the object is small and cheap to construct.
Modification to return the object by value:
SomeObject f() { return SomeObject(); }
SomeObject s(f());
Simple, clean, safe - no memory leaking here.
Using unique_ptr:
SomeObject* f() { return new SomeObject(); }
unique_ptr<SomeObject> s(f());
One of the advantages of using a unique_ptr or shared_ptr here is that you can change your function f at some point to return objects of a class derived from SomeObject and none of your client code will need to be changed - just make sure the base class (SomeObject) has a virtual constructor.
Why the options you were considering are not very good:
Variant 1:
SomeObject& s = f();
How are you going to destroy the object? You will need address of the object to call it's destructor anyway, so at some point you would need to dereference the object that s refers to (&s)
Variant 2. You have a leak here and not a chance to call destructor of the object returned from your function.

C++: Reference to dynamic memory

All considerations about when to use which aside, I am still unsure about pointer vs reference semantics.
Right now, I am under the impression that references are essentially pointers that must be initialized when they are declared, and then from that point on cannot point to anything else. In other words, they are a like a Type* const (not Type const*), or, they cannot be reseated. It essentially becomes a "new name" for that object. Now I heard that references do not actually need to be implemented by the compiler using pointers, but I am under the impression that you can still think of them this way, in regards to what their visible behavior will be.
But why can't you do something like this:
int& foo = new int;
I want to create a reference to dynamic memory. This does not compile. I get the error
error: invalid initialization of non-const reference of type 'int&' from a temporary of type 'int*'
That makes sense to me. It seems the new operator returns a pointer of given type to the address of memory that the OS? dynamically allocated for me.
So how do I create a "reference" to dynamic memory?
Edit: Links to resources that precisely explain the difference between references and pointers in C++ would be appreciated.
new returns a pointer to the allocated memory, So you need to capture the return value in a pointer.
You can create a reference to a pointer after allocation is done.
int *ptr = new int;
int* &ref = ptr;
then delete it after use as:
delete ref;
or more simply,
int &ref = *(new int);
delete it after use as:
delete &ref;
References are syntactic sugar. They allow one to access an object with the dot operator rather than the arrow.
Your choice of whether to use a pointer or a reference is semantic. When you pass an object by reference to a method, or return a reference from a method, you are saying: "This is my object and you may use it, but I own it (and it may be on the stack or the heap.)" It follows that the other answers here which suggest syntax like delete &foo; might technically work, but smell bad; If you have a reference to an object then you shouldn't be deleting it. You don't own it and, most importantly, as you can't reset the reference you end up with a reference to deallocated memory, which is a bad thing.
Now, if you have allocated an object on the heap (called 'new' to create it) then you do own it, and are responsible for cleaning it up later, so you need to hold a pointer to it. Why? So you can safely delete it later and null-out the pointer.
It follows that the difference between a pointer and a reference, other than the mechanical difference of using dot rather than arrow, is that by passing by reference to a method you indicate something about how an object should be used. To initialise a reference directly by calling new is nonsense, even if possible.
You can get a reference like this:
int& foo = *(new int);
In general, to get from T* to T& you use * to "dereference" the pointer.
However this is not a very good idea in the first place. You usually use pointers to store addresses of heap-allocated objects.