So I was writing a piece of code where I used new operator to create an object inside a local scope function and returned the reference as a pointer.
A* operator+(A that){
int sumA = a + that.getA();
int sumB = b + that.getB();
return new A(sumA, sumB);
}
In my thought It would not work because the object was created inside the local scope and should be temporary, but it compiled and ran. Can anyone explain to me about this? I am sure there are other things that kinda have the ability of breaking the scope and stuff.. If possible, could you give me some examples? Appreciated!
When you say "created inside local scope" what you really mean is "an automatic variable." Automatic variables are automatically destroyed when the scope in which they are created is exited from.
But new does not create an automatic variable. It creates a dynamically allocated object, whose lifetime is not bound by the scope in which it's created.
The object created by, new A(sumA, sumB) is not a temporary.
Values are returned from a local scope all the time. For example:
int f(int x)
{
int y = x*x;
return y;
}
While a variable would normally disappear when it falls out of scope, values returned from functions get special treatment by the compiler.
Regarding your example, you are creating an object on the heap and have a pointer to that object on the local stack. When your function returns the stack is cleaned up, that pointer along with it. Except - since you're returning the pointer to the caller, a copy of the pointer is passed back to the caller (probably through a cpu register).
As an aside: While this works fine, you need to be certain that the caller eventually deletes the returned object, else you'll have a memory leak.
C++ does not automatically manage memory for you. This means you must manually 'delete' any objects created dynamically with the 'new' operator. Your code is valid, but I think it doesn't accomplish what you wish. I think you are looking for something like this:
A operator+(const A& that){
int sumA = a + that.getA();
int sumB = b + that.getB();
return A(sumA, sumB);
}
Yes, the value created with new will still be alive after the function exits.
As others have mentioned, it is necessary to delete these objects to avoid memory leaks.
Because of this, best general C++ practice is to not return bare pointers like this function does, but to return some sort of smart pointer object such as shared_ptr. That way, you can return a pointer to the newly created object, and the object will be automatically destroyed once there are no more active references to it.
Related
I am reading the book c++ primer plus and I feel confused about the reference variables and pointers.
Here are two pieces of code extracted from page 400 of the book.
const free_throws & clone(free_throws & ft)
{
free_throws * pt;
*pt = ft;
return *pt;
}
const free_throws & clone2(free_throws & ft)
{
free_throws newguy;
newguy = ft;
return newguy;
}
The book said that the first one is okay but the second one is invalid. Is it true that a pointer variable will still exist after the function terminates even if it is declared within the function?
Another question is why can we omit the new keyword in the first piece of code? If we can just create a nameless structure and assign something to it, why do we need the new keyword?
Thank you in advance.
For the first one, the book provided a few lines of explanation.
The first statement creates a nameless free_throws structure. The pointer pt points to the structure, so *pt is the structure. The code appears to return the structure, but the function declaration indicates that the function really returns a reference to this structure.
Both functions have problems. The first function's problem is that pt does not point at a valid free_throws object, so doing *pt = ft; gives you undefined behaviour (you are assigning to a non-existent object). The second function's problem is that you're returning a reference to a local variable which will be destroyed when the function returns (a dangling reference).
Is it true that a pointer variable will still exist after the function terminates even if it is declared within the function?
No. A locally declared pointer is just like any other locally declared object - it will be automatically destroyed at the end of the function. The object that it points at may have a different lifetime, however.
Another question is why can we omit the new keyword in the first piece of code? If we can just create a nameless structure and assign something to it, why do we need the new keyword?
You can't.
If you want to create an object that lasts beyond the scope of a function, you can use a new-expression (like new free_throws()). This creates an object with dynamic lifetime, which you must later destroy manually with delete.
To demonstrate, your first function would be okay (at least not invoke undefined behaviour) if you dynamically allocated a free_throws object for pt to point to:
const free_throws & clone(free_throws & ft)
{
free_throws * pt = new free_throws();
*pt = ft;
return *pt;
}
However, it's still a really bad function because it really doesn't make it clear that the object being returned needs to be destroyed manually. Good C++ code will manage the ownership of dynamically allocated objects using smart pointers. At the very least, you should use raw pointers, simply because C++ developers know to look out for them, and document that your function dynamically allocates the objects it returns.
However, it is typically much better to write a function without any dynamic allocation at all. If you were to do that with this clone function though, you would just discover how pointless it is. Might as well just use the copy constructor instead of writing an extra function.
Hi i have few doubt related to heap variable...
I want to write a function as below ->
struct test
{
int x;
int y;
};
test* fun()
{
test *ptr = new test;
return ptr;
}
My doubt is returning a heap variable once it will go out of scope it will lost its value.
There is definitely a memory leak.(As heap variable is not deleted.)
So how can i design such kind of function.
Dynamically allocated objects (what you call heap variables) do not get destroyed at the end of the scope in which they were created. That's the whole point of dynamic allocation. While the test object is dynamically allocated, the pointer ptr is not - it will be destroyed when it goes out of scope. But that's okay! You copy the value of the pointer out of the function and this copy still points at the test object. The test object is still there. The function you've written is fine, but it isn't exactly good style.
Yes, there is a memory leak if nobody ever does delete on a pointer to the test object you created. That's a problem with returning raw pointers like this. You have to trust the caller to delete the object you're creating:
void caller()
{
test* p = fun();
// Caller must remember to do this:
delete p;
}
A common C-style way of doing this (which is definitely not recommended in C++) is to have a create_test and destroy_test pair of functions. This still puts the same responsibility on the caller:
void caller()
{
test* p = create_test();
// Caller must remember to do this:
destroy_test(p);
}
The best way to get around this is to not use dynamic allocation. Just create a test object on the stack and copy it (or move it) out of the function:
test fun()
{
test t;
return t;
}
If you need dynamic allocation, then you should use a smart pointer. Specifically, the unique_ptr type is what you want here:
std::unique_ptr<test> fun()
{
return std::unique_ptr<test>(new test());
}
The calling function can then handle the unique_ptr without having to worry about doing delete on it. When the unique_ptr goes out of scope, it will automatically delete the test object you created. The caller can however pass it elsewhere if it wants some other function to have the object.
You are not returning a heap variable, you are returning a value of a stack variable that holds a pointer to the heap. The stack variable goes out of scope; the memory pointed to by the pointer is in the heap - it never goes out of scope.
There will be a memory leak unless you release the memory in the caller.
My doubt is [that] returning a heap variable once it will go out of scope it will lo[se] its value.
No worry, because since you're returing the pointer by value; so the pointer will go out of scope, but since you're returning the memory that it points to, there is no memory leak (only if we can rely on the caller to delete it).
However, if we had returned the pointer by reference then we would have a problem:
test*& fun() // note the & (reference)
{
test *ptr = new test;
return ptr;
}
Here you're returning a reference to a temporary. When the variable goes out of scope you will be using an object that doesn't exist. This is why you can't return temporaries by reference.
My doubt is returning a heap variable once it will go out of scope it will lost its value.
No heap variable does not go out of scope as do go stack variables...
There is definitely a memory leak.(As heap variable is not deleted.)
Yes we have to free memory allocated on heap by ourself, otherwise there is memory leak...
I would suggest to read some tutorial related to it.
I am still new to C++. I have found that you can instantiate an instance in C++ with two different ways:
// First way
Foo foo;
foo.do_something();
// Second way
Baz *baz = new Baz();
baz->do_something();
And with both I don't see big difference and can access the attributes. Which is the preferred way in C++? Or if the question is not relevant, when do we use which and what is the difference between the two?
Thank you for your help.
The question is not relevant: there's no preferred way, those just do different things.
C++ both has value and reference semantics. When a function asks for a value, it means you'll pass it a copy of your whole object. When it asks for a reference (or a pointer), you'll only pass it the memory address of that object. Both semantics are convertible, that is, if you get a value, you can get a reference or a pointer to it and then use it, and when you get a reference you can get its value and use it. Take this example:
void foo(int bar) { bar = 4; }
void foo(int* bar) { *bar = 4; }
void test()
{
int someNumber = 3;
foo(someNumber); // calls foo(int)
std::cout << someNumber << std::endl;
// printed 3: someNumber was not modified because of value semantics,
// as we passed a copy of someNumber to foo, changes were not repercuted
// to our local version
foo(&someNumber); // calls foo(int*)
std::cout << someNumber << std::endl;
// printed 4: someNumber was modified, because passing a pointer lets people
// change the pointed value
}
It is a very, very common thing to create a reference to a value (i.e. get the pointer of a value), because references are very useful, especially for complex types, where passing a reference notably avoids a possibly costly copy operation.
Now, the instantiation way you'll use depends on what you want to achieve. The first way you've shown uses automatic storage; the second uses the heap.
The main difference is that objects on automatic storage are destroyed with the scope in which they existed (a scope being roughly defined as a pair of matching curly braces). This means that you must not ever return a reference to an object allocated on automatic storage from a regular function, because by the time your function returns, the object will have been destroyed and its memory space may be reused for anything at any later point by your program. (There are also performance benefits for objects allocated on automatic storage because your OS doesn't have to look up a place where it might put your new object.)
Objects on the heap, on the other hand, continue to exist until they are explicitly deleted by a delete statement. There is an OS- and platform-dependant performance overhead to this, since your OS needs to look up your program's memory to find a large enough unoccupied place to create your object at. Since C++ is not garbage-collected, you must instruct your program when it is the time to delete an object on the heap. Failure to do so leads to leaks: objects on the heap that are no longer referenced by any variable, but were not explicitly deleted and therefore will exist until your program exits.
So it's a matter of tradeoff. Either you accept that your values can't outlive your functions, or you accept that you must explicitly delete it yourself at some point. Other than that, both ways of allocating objects are valid and work as expected.
For further reference, automatic storage means that the object is allocated wherever its parent scope was. For instance, if you have a class Foo that contains a std::string, the std::string will exist wherever you allocate your Foo object.
class Foo
{
public:
// in this context, automatic storage refers to wherever Foo will be allocated
std::string a;
};
int foo()
{
// in this context, automatic storage refers to your program's stack
Foo bar; // 'bar' is on the stack, so 'a' is on the stack
Foo* baz = new Foo; // 'baz' is on the heap, so 'a' is on the heap too
// but still, in both cases 'a' will be deleted once the holding object
// is destroyed
}
As stated above, you cannot directly leak objects that reside on automatic storage, but you cannot use them once the scope in which they were created is destroyed. For instance:
int* foo()
{
int a; // cannot be leaked: automatically managed by the function scope
return &a; // BAD: a doesn't exist anymore
}
int* foo()
{
int* a = new int; // can be leaked
return a; // NOT AS BAD: now the pointer points to somewhere valid,
// but you eventually need to call `delete a` to release the memory
}
The first way -- "allocating on the stack" -- is generally faster and preferred much of the time. The constructed object is destroyed when the function returns. This is both a blessing -- no memory leaks! -- and a curse, because you can't create an object that lives for a longer time.
The second way -- "allocating on the heap" is slower, and you have to manually delete the objects at some point. But it has the advantage that the objects can live on until you delete them.
The first way allocates the object on the stack (though the class itself may have heap-allocated members). The second way allocates the object on the heap, and must be explicitly delete'd later.
It's not like in languages like Java or C# where objects are always heap-allocated.
They do very different things. The first one allocates an object on the stack, the 2nd on the heap. The stack allocation only lasts for the lifetime of the declaring method; the heap allocation lasts until you delete the object.
The second way is the only way to dynamically allocate objects, but comes with the added complexity that you must remember to return that memory to the operating system (via delete/delete[]) when you are done with it.
The first way will create the object on the stack, and the object will go away when you return from the function it was created in.
The second way will create the object on the heap, and the object will stick around until you call delete foo;.
If the object is just a temporary variable, the first way is better. If it's more permanent data, the second way is better - just remember to call delete when you're finally done with it so you don't build up cruft on your heap.
Hope this helps!
For example this class:
class RTPIPv4Address{
public:
RTPIPv4Address(int a, int b);
}
Silly question but... I just stumbled on code which initialized a class instance like that with for example
RTPIPv4Address adr(2,2);
Now I am wondering, is this just another syntax for the usual
RTPIPv4Address* adr = new RTPIPv4Address (2,2);
or does it have any other effects? For example, given the lack of a pointer and a new(), is it declared on the stack like other local variables do and then get deallocated at function return or is it saved on the heap and therefore persist?
Thanks in advance
Yes, the first example is stack-allocated and will have it's destructor called and be deallocated as soon as the variable loses scope. For a local variable, this usually happens when the function returns, though you can force it to lose scope earlier with curly braces.
function
{
RTPIPv4Address adr(2,2);
return; //adr loses scope and destructor is called
}
That's how it's normally allocated on the stack and where it loses scope, but it can happen other places as well.
function
{
if (condition)
{
RTPIPv4Address adr(2, 2);
//do stuff with adr
} //adr loses scope and destructor is called
//do more stuff
return;
}
The two both construct an object but apart from that are very dissimilar. The first constructs on the stack, the second on the heap. The first form should be used wherever possible. The second form should be used if and only if you need the object to persist, or, it is too large to fit on the stack. new is not the "usual" form of object creation at all in C++.
The first example will stack-allocate your object. The only way to get something on the heap is via new (and, obviously, malloc or other low-level operations like mmap).
Using C++:
I currently have a method in which if an event occurs an object is created, and a pointer to that object is stored in a vector of pointers to objects of that class. However, since objects are destroyed once the local scope ends, does this mean that the pointer I stored to the object in the vector is now null or undefined? If so, are there any general ways to get around this - I'm assuming the best way would be to allocate on the heap.
I ask this because when I try to access the vector and do operations on the contents I am getting odd behavior, and I'm not sure if this could be the cause or if it's something totally unrelated.
It depends on how you allocate the object. If you allocate the object as an auto variable, (i.e. on the stack), then any pointer to that object will become invalid once the object goes out of scope, and so dereferencing the pointer will lead to undefined behavior.
For example:
Object* pointer;
{
Object myobject;
pointer = &myobject;
}
pointer->doSomething(); // <--- INVALID! myobject is now out of scope
If, however, you allocate the object on the Heap, using the new operator, then the object will remain valid even after you exit the local scope. However, remember that there is no automatic garbage collection in C++, and so you must remember to delete the object or you will have a memory leak.
So if I understand correctly you have described the following scenario:
class MyClass
{
public:
int a;
SomeOtherClass b;
};
void Test()
{
std::vector<MyClass*> v;
for (int i=0; i < 10; ++i)
{
MyClass b;
v.push_back(&b);
}
// now v holds 10 items pointers to strange and scary places.
}
This is definitely bad.
There are two primary alternatives:
allocate the objects on the heap using new.
make the vector hold instances of MyClass (i.e. std::vector<MyClass>)
I generally prefer the second option when possible. This is because I don't have to worry about manually deallocating memory, the vector does it for me. It is also often more efficient. The only problem, is that I would have to be sure to create a copy constructor for MyClass. That means a constructor of the form MyClass(const MyClass& other) { ... }.
If you store a pointer to an object, and that object is destroyed (e.g. goes out of scope), that pointer will not be null, but if you try to use it you will get undefined behavior. So if one of the pointers in your vector points to a stack-allocated object, and that object goes out of scope, that pointer will become impossible to use safely. In particular, there's no way to tell whether a pointer points to a valid object or not; you just have to write your program in such a way that pointers never ever ever point to destroyed objects.
To get around this, you can use new to allocate space for your object on the heap. Then it won't be destroyed until you delete it. However, this takes a little care to get right as you have to make sure that your object isn't destroyed too early (leaving another 'dangling pointer' problem like the one you have now) or too late (creating a memory leak).
To get around that, the common approach in C++ is to use what's called (with varying degrees of accuracy) a smart pointer. If you're new to C++ you probably shouldn't worry about these yet, but if you're feeling ambitious (or frustrated with memory corruption bugs), check out shared_ptr from the Boost library.
If you have a local variable, such as an int counter, then it will be out of scope when you exit the function, but, unless you have a C++ with a garbage collector, then your pointer will be in scope, as you have some global vector that points to your object, as long as you did a new for the pointer.
I haven't seen a situation where I have done new and my memory was freed without me doing anything.
To check (in no particular order):
Did you hit an exception during construction of member objects whose pointers you store?
Do you have a null-pointer in the container that you dereference?
Are you using the vector object after it goes out of scope? (Looks unlikely, but I still have to ask.)
Are you cleaning up properly?
Here's a sample to help you along:
void SomeClass::Erase(std::vector<YourType*> &a)
{
for( size_t i = 0; i < a.size(); i++ ) delete a[i];
a.clear();
}