This is not exactly my code but it looks a lot like it
I have 2 tables of type CTable. They work in the same way as normal arrays but can be allocated dynamically and resized. So lets just pretend that they are arrays right now
One table has object references
MyObj obj1;
MyObj obj2;
MyObj table1[10];
table1[0] = obj1;
table1[1] = obj2;
Now because I want to order them differently sometimes, I've put pointers to these objects in another table
MyObj *table2[10];
table2[0] = &table1[0];
table2[1] = &table1[1];
Is there a way to get a reference to obj1 and obj2 through table2 so those object will get out of scope at the end of some kind of delete function
something like
void free() {
MyObj &obj = *table2[0];
}
and then bang, at the end of free, obj is delete automagically. Also, some kind of way to delete these objects through table2 would be acceptable.
If you want to control the objects' lifetime, you'll need to allocate them dynamically. In that case, your code would look something like this:
vect2.push_back(new MyObj);
vect2.push_back(new MyObj);
void func() {
MyObj &obj = *vect2[0];
// ...
vect2.erase(vect2.begin());
delete &obj;
}
In your case it good to be a one vector with just only pointers.
If it doesn't fits try this:
for(UINT i=0;i<vect1.size();++i)
{
MyObj * p = &vect1[i];
vect2.push_back(p);
}
// This is example of adding
P.S.
vector<MyObj*> vect2;
vect2.push_back(&obj1);
vect2.push_back(&obj2);
this code is wrong
Related
Ok, here i have 2 simple C++ examples, the first one is:
MyClass
class MyClass
{
private:
int test;
public:
int member(){
test = 456;
return 1;
} // one public function
};
global function definition
int funct(MyClass** obj)
{
*obj = new MyClass();
int c = (**obj).member();
return 1;
}
main
...
MyClass* object;
int i = funct(&object);
...
while in the second case, i modify the main like this:
MyClass** object = (MyClass **)malloc(sizeof(MyClass));
int i = fun(object);
Both examples work fine, but i'm not sure if i understood correctly why ONLY in this second case i need a malloc (otherwise it wouldn't compile at all).
Thanks in advance for your help
PS: i know double pointers are more C-style programming, but i'm currently experimenting with both languages.
MyClass** object = (MyClass **)malloc(sizeof(MyClass));
actually this is wrong, malloc will return pointer to allocated memory: MyClass *, so if you later do: *object and would like to see a pointer to MyClass you will be wrong. You should rather:
MyClass* pobject = (MyClass *)malloc(sizeof(MyClass));
MyClass** ppobject = &pobject ;
your question is unclear to me - sorry,also it is not wise to allocate clases with malloc - your one looks like its POD - so it seems to be safe, but I would check it with std::is_pod.
[edit]
working example is below. You asked why you need initialization of object in the second case, thats because in first case you reserve storage for your pointer by simply defining pointer variable : MyClass* object;. Here object can be safely used in funct. In second example, you dont have reserved memory (in this case space on stack) for your pointer to MyClass, so you must allocate it with malloc or new. Hopefully thats clear enough.
MyClass** object = (MyClass **)malloc(sizeof(MyClass*));
//MyClass** object = new MyClass*;
int i = funct(object);
delete *object;
free(object);
//delete object;
First of all, you have a bug (and the whole thing works only because sizeof(MyClass)>=sizeof(MyClass*)):
MyClass** object = (MyClass **)malloc(sizeof(MyClass));
is incorrect, should be
MyClass** object = (MyClass **)malloc(sizeof(MyClass*));
or
MyClass** object = new MyClass*;
Second, you do need malloc() (or new) because you need your double pointer MyClass** to point to some instance of MyClass*. Your first and second (after correction) example differ only in a way where you get this MyClass* - in first example it is on-stack, in second example it is on heap.
Oh, and when it on heap, you need to manually call free() (if malloc() was used to allocate it) or delete (if new was used) for the pointer.
I deleted my previous answer. This is how you should go about initializing the double pointer:
MyClass** object;
object = new MyClass*;
int i = funct(object);
The second line allocates a new pointer to an instance of MyClass, and the call to funct allocates an actual object of MyClass. After this call, object will point to a valid pointer to a valid instance of MyClass.
I've been trying to figure this out but can't quite get my head round it.
Say I declare an object in a header file such as:
#ifndef SOMECLASS_H
#define SOMECLASS_H
#include "otherclass.h"
class SomeClass
{
public:
SomeClass();
OtherClass *obj;
};
#endif // SOMECLASS_H
Can I do the following in my code?
obj = new OtherClass();
//Do something
delete obj;
obj = new OtherClass();
//Do something else
delete obj;
Or would I have to create a new obj?
I can't really think of a reason why I might need to do this but I'd like to know if it would work and also whether or not it would be a good idea (I know it's best to create objects on the stack generally but for the sake of argument let's say in this case it isn't an option).
I think you need to adjust your mental model of what's happening. Let's look at a simpler case where we don't have the SomeClass class:
int main() {
OtherClass *obj = new OtherClass();
delete obj;
obj = new OtherClass();
delete obj;
}
The first line is this function is a declaration. This declaration introduces an object called obj whose type is OtherClass*. The important thing here is that obj is just a pointer. It's not an OtherClass object. It just holds the address of one. So when you talk about the object obj, you are talking about the pointer.
This declaration has an initialiser which is = new OtherClass(). The expression new OtherClass() also introduces an object, but this time it is not named. This object has type OtherClass. The expression returns a pointer to that OtherClass object which you are using to initialise obj. So now the obj pointer object is pointing at the OtherClass object.
The memory model for this looks something like this:
obj
+-------------+ +------------+
| OtherClass* |----->| OtherClass |
+-------------+ +------------+
Now, you can use an object during its lifetime. The lifetime of obj is the scope of the function we declared it in. At the end of the function, obj goes out of scope and is destroyed. That is, the pointer is destroyed. The lifetime of the OtherClass object lasts up until we use delete on a pointer to it. The delete only destroys the OtherClass object and not the pointer. So after the first delete, we have this:
obj
+-------------+
| OtherClass* |----->
+-------------+
The pointer still exists. It's still pointing to the same place even, but the object that was there is now gone.
At this point, we can't attempt to use the OtherClass object, since it doesn't exist any more. However, we can certainly reuse the pointer object obj. When we do obj = new OtherClass() (which is an expression, not a declaration), we create a new OtherClass object and set obj to point at it. We're back to this situation:
obj
+-------------+ +------------+
| OtherClass* |----->| OtherClass |
+-------------+ +------------+
And then we delete it again.
The only difference between this example and your example is that obj is a member of SomeClass. Each object of type SomeClass will contain within it an OtherClass* pointer called obj. The lifetime of obj now is whatever the lifetime of the SomeClass object is. As long as that object is still alive, you can use obj in whatever way you like. Of course, if you delete the object it is pointing at, you cannot use that object.
Your code is ok.
If you want you can reuse your pointer any time you want.
obj = new OtherClass();
delete obj;
obj = new OtherClass();
remeber that when you call delete you call OtherClass destructor.
it is good practice, but not required, put pointer to zero after delete.
obj = 0;
This because, if after delete pointer you want to test, for instance
if(!obj) {
...
}
it is said that !obj == true.
Your code is fine, but in C++11 consider using unique_ptr to avoid having to call "delete" manually. Eg:
std::unique_ptr<OtherClass> obj(new OtherClass());
//Do something
obj.reset(new OtherClass()); //this deletes the previous object
//Do something else. The object will be deleted when obj goes out of scope.
Also you might want to consider changing your title to something like, "Can I reassign a pointer after deleting the object it points to?"
Yes it would work. When you do the second
obj = new OtherClass();
the obj points to deleted memory, but you set it to new value. There is nothing wrong with it.
Your code is fine.
Depending on how OtherClass works, you may consider doing:
obj = new OtherClass();
//Do something
// then do something else
delete obj;
But this is not always feasible. Should this not be applicable in your case, what you are currently doing is OK.
I'd just do obj = NULL; after the second delete. Just in case I need to test this pointer's value somewhere else, to determine whether it is in use or not.
To sum up : you can't use an instance of a class that has been deleted, but you can reuse the variable pointer which was used to store the address of the instance.
That is to say, you CANNOT do the following (from your code sample) :
obj = new OtherClass();
delete obj;
obj->objMethod(); // dereferencing a now invalid pointer => dangerous.
But you can do what you wrote in your question :
obj = new OtherClass();
//Do something
delete obj;
obj = new OtherClass();
//Do something else
delete obj;
Actually, the last sample of code is as valid as the following (with a simple int) :
int i = 42;
// Do something
i = 15;
// Do something
I've a simply question.
I have been looking for the answer but I might not found the correct tags or words to find the solution...
The question is, as the title says: Do local variables (which have reserved memory) need to be freed? I meant, for example, if I've got the following function:
myClass* myFunction(){
myClass* A = new myClass;
return A;
}
In case of "yes", where Should I call "delete"? both before and after "return" are nonsense...
Am I right?
Don't use new unless you need to.
This avoids new, and so doesn't need deleting
myClass myFunction(){
myClass A;
return A;
}
If you think you need pointers, consider using smart pointers.
If you want the excitement of raw pointers, this function returns a raw pointer to the caller, and they must delete it when they are done.
myClass * myFunction(){
myClass * A = new myClass;
return A;
}
myClass * thing = myFunction();
//stuff, that might throw an exception, so watch it
// smart pointers FTW
delete thing;
Assuming that your type is defined something like this:
class myClass { /* ... */ };
Your example is not proper C++ (unless you have a myClass* conversion constructor, which you probably don't).
You do not have to new an object that sits on automatic memory:
myClass myFunction(){
myClass a;
return a;
}
When newing an object on dynamic memory, you can then put it into a pointer variable in automatic memory:
myClass* myFunction(){
myClass* a = new myClass;
return a;
}
Here, a might leak, if it isn't freed by the caller.
Presumably, unless you're doing some interesting operator overloading, you mean to assign new myClass to a pointer and return the pointer
myClass *myFunction(){
myClass *A = new myClass;
return A;
}
If that is the case, then yes, you will have to delete it at some point. It will be up to the caller of this function to keep the pointer and delete it when appropriate.
Alternatively you can use smartpointers.
Use shared_ptr instead of raw pointers.
std::shared_ptr<myClass> myFunction()
{
std::shared_ptr<myClass> A = std::make_shared<myClass>(constructor parameters, if any);
return A;
}
void f()
{
std::shared_ptr<myClass> A = myFunction();
}
This will emulate Java-style garbage collection.
I have the following code:
vector<SomeClass> objs;
SomeClass obj; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue()){
use(&obj);
obj = new SomeClass(); // create a new obj with an existing name
objs.pushback(obj)
}
in this code new SomeClass(); is in java OOP form - and is not a c++ code. what code should be used instead of obj = new SomeClass();?
The answer is:
obj = SomeClass();
new SomeClass() will return pointer to SomeClass object. You cannot assign it to varible obj, which type is SomeClass, not SomeClass*.
EDIT: If I remember well, SomeClass obj(); should also work.
I think what you wanted is something like that:
vector<SomeClass *> objs;
SomeClass* obj = new SomeClass; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue())
{
use(&obj);
obj = new SomeClass; // create a new obj with an existing name
objs.push_back(obj)
}
Your understanding of the language is somewhat off. Here is your code as annotated:
vector<SomeClass> objs;
SomeClass obj; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue()){
use(&obj);
obj = new SomeClass(); // create a new obj with an existing name
objs.pushback(obj)
}
Here is what ACTUALLY happens
// create an object called "objs" which is a std::vector header, on the stack.
vector<SomeClass> objs;
// create an instace of "SomeClass" on the stack, call it obj.
SomeClass obj;
// allocate storage in the heap for some number of SomeClass instances to
// act as the storage for "objs", and assign them to it's "m_data" member.
// default construct the first one,
// then call it's copy constructor with the stack instance of "Obj" to
// copy the values/data into the first entry of the heap allocation of objs.
objs.push_back(obj);
while (someConditionIsTrue()){
// pass a pointer to the stack-allocated instance of obj.
use(&obj);
// create a new instance of "SomeClass" on the heap,
// default/zero construct it,
// return the pointer to this heap allocation and pass it
// to obj.operator=(const SomeClass*) to copy the data into
// the stack space allocated for "obj".
obj = new SomeClass(); // create a new obj with an existing name
// leak the pointer to the previous heap allocation by not storing it.
// increase the size of the heap allocation backing objs and then
// default construct the first SomeClass instance in the new space,
// then copy our freshly copy-initialized stack instance back into it.
objs.pushback(obj)
}
You could write this code numerous other ways, but it seems like the most sensible would be.
std::vector<SomeClass> objs;
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1); // grow me a new element.
use(&objs.back());
}
Or make "use" take a reference.
void use(SomeClass& obj);
//...
use(objs.back());
If you really want a local object to try the entry.
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1);
// the compiler will either optimize this out entirely,
// or use a pointer under the hood.
SomeClass& obj = objs.back();
use(&obj); // take the address of the object obj references.
}
Also, be aware that "resize()" can get expensive. You might want to do this upfront:
objs.reserve(1024); // or something you know is likely to cover most use cases.
If you really, really have to use a pointer.
SomeClass* obj = nullptr;
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1);
obj = &objs.back();
use(obj);
}
Instead of "objs.resize()" you may be able to use placement-new with a ctor:
objs.emplace_back(SomeClass());
Others have suggested that you use
obj = Someclass();
But note that this is copying a default-constructed stack copy of the object.
{
SomeClass tempObj;
obj.operator=(std::move(tempObj));
}
I don't think that's what you actually want to do. It's more expensive than just having a stack-local copy like this:
while (someCondition()) {
SomeClass stackCopy;
...
}
the compiler is smart enough not to give up the stack space each loop. What it will do is a thing called "Placement new" to re-invoke the constructor on the same object:
SomeClass obj;
while (someCondition()) {
new (&obj) SomeClass(); // Call SomeClass() ctor on the memory at &obj
...
}
But - this is basically how the compiler achieved my previous code sample.
I know that I can't get a reference of a local var. such as:
int& func1()
{
int i;
i = 1;
return i;
}
And I know that this is correct, but I have to delete it after calling func2()
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int *p = func2();
cout << *p << endl;
delete p;
return 0;
}
If the function is like this:
MyClass MyFunction()
{
return new MyClass;
}
MyClass's whole definition is:
class MyClass
{
public:
MyClass() : num(1){}
MyClass(MyClass*) : num(10){}
int num;
};
Will this cause memory leak?
How should I avoid it?
the function returns an object not a pointer, so how can I delete it?
PS: the code comes from the book "Ruminations on C++" Chapter 10.
the original code is:
Picture frame(const Pictrue& pic)
{
// Picture has a constructor Picture(*P_Node)
// Frame_Pic derives from P_Node
// So the constructor Picture(*P_Node) will implicitly convert Frame_Pic to Picture.
return new Frame_Pic(pic);
}
MyClass MyFunction()
{
return new MyClass;
}
This is actually wrong.you are returning a pointer .
so it should be
MyClass* MyFunction()
if your function is as i mentioned above and if you are not deleting it after using it.it will leak memory.
How should I avoid it? the function returns an object not a pointer, so how can I delete it?
that is a compilation error.so the point of deleting it will not rise
If you delete the pointer returned from the funciton there is no memory leak. However this is error prone since it means that every client of the function must know that it should delete the return value. It's much better style to use a smart pointer (either shared_ptr or unique_ptr according to semantics).
The same goes to the Picture example. If this object correctly manages its resources (i.e. deletes in the destructor and has a good copy constructor and operator= (in accordance with the Rule of Three), then there is no memory leak.
With your updated MyClass that has the pointer constructor, I suppose you should write:
MyClass MyFunction() {
MyClass *ptr = new MyClass;
MyClass retval(ptr);
delete ptr; // the dynamically-allocated object isn't needed any more
return retval;
}
That happens to be exception-safe, since the constructor of MyClass can't throw, but as a general rule you really shouldn't ever call new without putting the result straight into a smart pointer:
MyClass MyFunction() {
std::unique_ptr<MyClass>(new MyClass);
return MyClass(ptr);
}
It's a fairly absurd situation anyway - if you're going to return by value, there's no reason to call new at all:
MyClass MyFunction() {
MyClass tmpvalue;
return &tmpvalue; // doesn't actually return the pointer, just an object
// constructed from it
}
And since the value of the pointer isn't even used by the pointer constructor, you could just as well write:
MyClass MyFunction() {
return 0; // returns an object constructed from a null pointer
}
In the original code your quote from the book, I guess that the class Picture has a data member of type P_Node*, in which it stores the pointer value, and calls delete on that pointer in its destructor. Hopefully the author also does something about the copy constructor and copy assignment operator of Picture, to prevent a double-free after the copy. I don't have the book, so I can't check my guess, but the code for Picture should show how it's done.
[Edit: oh, that's one of the books by Koenig and Moo. They are (more than) competent, so pretty certainly their Picture class handles the resource correctly. If it doesn't, it's because it's a deliberate example of Doing It Wrong.]
It's the same as your "func2" example. who ever call "frame" need to free the returning Picture in the end.
MyClass MyFunction()
{
return new MyClass;
}
is incorrect, because operator new returns a pointer to MyClass, but your function returns MyClass, not MyClass*
A simple check would be this:
If you're using N number of new in your program, then you've to use N number of compatible1 delete in your program to avoid memory leak2.
So are you doing that? Yes, in the first case (in which you're doing new int) you're doint that. There is no memory leak.
And rest of the post isn't clear enough to me!
1. By compatible delete, I mean if you're using new in the form of ptr = new T[M], then the compatible delete should be of the form of delete []ptr. Similarly, delete ptr is compatible with ptr = new T.
2. Of course, if you're using some smart pointers, then you don't have to use delete explictly.