I'm implementing a simplified unique pointer. Everything was pretty clear, but I wonder about the destructor in my class.
Should it be ~unique_pointer(){obj->~T();} or ~unique_pointer(){delete obj}?
I really don't see a difference between these. Can you explain how they work?
Below is the whole class:
template<class T>
class unique_pointer{
private:
T*obj;
public:
unique_pointer(const T* obj):obj{obj}{}
~unique_pointer(){obj->~T();}
T operator*() const { return *obj; }
T* operator->() const { return obj; }
T* release(){
T* temp = obj;
obj = 0;
return obj;
}
};
It should be ~unique_pointer(){obj->~T();} or ~unique_pointer(){delete obj}. I really don't see difference between each other.
obj->~T() destroys the pointed object. If the object is stored in dynamic memory, then the memory is not dealloated. If nothing else deallocates the memory, then the memory is leaked. Given that the point of a unique pointer is to manage dynamic allocation, doing this would be rather pointless.
delete obj If obj was created with allocating new, then this destroys the object and frees the deallocation. Otherwise the behaviour of the program is undefined. This is what std::default_delete, the default deleter of std::unique_ptr, does (unless the template type argument is T[] in which case it calls delete[] instead).
Some simple rules of thumb that apply to most cases:
If you new, then delete
Delete only if you newed
Never delete more than once
If you newed an array, then delete[] instead
Don't use new nor delete except in implementation of a smart pointer or similar low level memory management class
If you malloc, then free
Never free more than once
Don't malloc
If you placement new, then call destructor explicitly
Don't placement new unless you know what you're doing
P.S. Your release doesn't seem to make sense, as it doesn't release obj, has an unused variable temp, and uses some undeclared val.
Furthermore, it is copyable and have undefined behaviour if copied or moved. A unique pointer shouldn't be copyable, and needs a custom definition for move.
Related
If a c++ resource is managed via unique_ptr then does the destructor of the class need to free the heap memory it allocated or it gets free automatically when the unique_ptr goes out of scope? For eg. In below example if I plan to create a unique_ptr to Entity class and I don't add delete in destructor then what will happen?
class Entity
{
private:
int* data;
public:
explicit Entity(const int size) { data = new int[size]; } // acquire
~Entity() { delete[] data; } // release
void do_something() {}
};
void functionUsingEntity() {
Entity e(100); // lifetime automatically tied to enclosing scope
e.do_something();
} // automatic destruction and deallocation for e
int* data;
This is a pointer. When a pointer is destroyed, nothing happens to whatever it points to. If it is a last pointer to a dynamic allocation when it's destroyed, then that allocation will leak.
explicit Entity(const int size) { data = new int[size]; } // acquire
^^^^^^^^^^^^^^
Here, you allocate a dynamic array. If you don't deallocate it using delete[], then it will leak.
If a c++ resource is managed via unique_ptr then does the destructor of the class need to free the heap memory it allocated or it gets free automatically when the unique_ptr goes out of scope?
If a resource is owned by std::unique_ptr, then the destructor of std::unique_ptr will delete the resource. The dynamic array that you allocated is not owned by a std::unique_ptr. In order for it to be owned by a std::unique_ptr, you must change the type of the member to be a std::unique_ptr.
In below example if I plan to create a unique_ptr to Entity class and I don't add delete in destructor then what will happen?
Then the allocation that is not owned by a unique pointer will leak.
~Entity() { delete[] data; } // release
This is an incomplete attempt at implementing the RAII pattern. In order for deletion in the destructor to be correct, you must first ensure that the pointer is unique. That isn't currently enforced because your copy/move constructors and copy/move assignment operators make a copy of the pointer. Using any of those will result in undefined behaviour. You should follow the rule of 5 if you delete anything in the destructor.
Or, a better design would be to use an existing RAII class such as a smart pointer or a container i.e. follow the rule of 0:
class Entity
{
private:
std::unique_ptr<int[]> data;
public:
explicit Entity(const int size) : data(std::make_unique<int[]>(size)) {}
When you create a std::unique_ptr<Entity> ptr to class Entity, and when ptr goes out of scope, it invokes the destructor of the class Entity. Now, if class Entity allocates any memory(as in this case) or is holding other resources, it is the responsibility of the destructor of class Entity to free the memory and release the resources. If you don't free the memory in the destructor, your application will end-up leaking memory.
I've this C++ class:
class test{
char* p;
SomeClass* someObject;
test(){
...
p = (char*) malloc(1000);
someObject = new SomeClass();
...
}
~test(){}
}
Do I need to call free(p) or delete someObject explicitly in test destructor in order to free their allocated memory or that memory will free automatically?
You need to free all dynamically allocated memory in the destructor. This does not get done automatically.
Your class contains two pointers, and essentially has no control over what these point to. In fact, these could point to objects that you are not allowed to delete, for example:
struct Foo {};
struct Bar {
Foo* f_;
Foo(Foo* f) : f(f_) {}
};
int main() {
Foo f;
Bas b(&f); // b has a Foo ptr, but should it delete it?
}
So you can see that it doesn't really make sense for pointer data members to be deleted automatically.
As a general rule, if your class manages resources1, then you should take care of copy construction and assignment; that means, you should either disable them if that makes sense for the class, or provide implementation for them because the compiler generated ones would not work. For detail discussion on this topic, see the rule of three, and extensive discussions on stackoverflow:
What is The Rule of Three?
Rule-of-Three becomes Rule-of-Five with C++11?
If you don't follow this rule, then the default copy constructor and assignment operation will make a shallow copy and you will have more than one instance having pointers to the same dynamically allocated objects, which they will all try to delete upon destruction.
You can avoid manually deleting objects created with new by using smart pointers. In your case, where the class obviously owns the dynamically allocated object,you should look at C++11's std::unique_ptr or boost::scoped_ptr
Finally, you can really avoid all memory management problems by avoiding pointers all together, unless you really need to. You could replace your char* by an std::string for example:
class test{
std::string p;
SomeClass someObject;
//test() : someObject() {} // default construction is probably OK...
};
1. That is, it allocates and deallocates memory, or opens and closes network connection, or creates and destroy mutexes and so on.
Yes, you have to free anything you malloc and delete everything you new.
You can also avoid that by not storing pointers in your class.
class test{
public:
std::string p;
SomeClass someObject;
};
Yes, you need.
If you don't want, you can use the Smart Pointer
Yes, you need to free them explicitly. Pointer as a data type does not have any destructor. Compiler/execution enviroment does not have any means to guess if pointer points to anything meaningfull or not. Even if the value is meaningfull, it may point to some static object for example. Or it can point to some field of a bigger object. Compiler is not doing any automatic cleanup on pointers.
The memory is technically leaked if you do not reclaim it when the instance of test is destructed. You could use a smart pointer instead to avoid calling free or delete explicitly in the destructor.
struct Free { void operator () (void *p) const { free(p); } };
class test {
std::unique_ptr<char, Free> p;
std::unique_ptr<SomeClass> someObject;
test () : p(static_cast<char *>(malloc(1000)),
someObject(new SomeClass)
{ //...
}
~test () {}
};
This uses the destructor of the smart pointer to perform the clean up action for you.
If test were only used as const global instances, then it is less important to implement the cleanup since the memory would not be reclaimed until the execution had ended anyway. But it is good practice to always implement the cleanup, because it would make the code correct now, and test may be used differently in the future.
Assume a pointer object is being allocated on one point and it is being returned to different nested functions. At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone.
Is there any guarantee that any of these will work?
if(ptr != NULL)
delete ptr;
OR
if(ptr)
delete ptr;
This code does not work. It always gives Segmentation Fault
#include <iostream>
class A
{
public:
int x;
A(int a){ x=a;}
~A()
{
if(this || this != NULL)
delete this;
}
};
int main()
{
A *a = new A(3);
delete a;
a=NULL;
}
EDIT
Whenever we talk about pointers, people start asking, why not use Smart Pointers.
Just because smart pointers are there, everyone cannot use it.
We may be working on systems which use old style pointers. We cannot convert all of them to smart pointers, one fine day.
if(ptr != NULL) delete ptr;
OR
if(ptr) delete ptr;
The two are actually equivalent, and also the same as delete ptr;, because calling delete on a NULL pointer is guaranteed to work (as in, it does nothing).
And they are not guaranteed to work if ptr is a dangling pointer.
Meaning:
int* x = new int;
int* ptr = x;
//ptr and x point to the same location
delete x;
//x is deleted, but ptr still points to the same location
x = NULL;
//even if x is set to NULL, ptr is not changed
if (ptr) //this is true
delete ptr; //this invokes undefined behavior
In your specific code, you get the exception because you call delete this in the destructor, which in turn calls the destructor again. Since this is never NULL, you'll get a STACK OVERFLOW because the destructor will go uncontrollably recursive.
Do not call delete this in the destructor:
5.3.5, Delete: If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will
invoke the destructor (if any) for the object or the elements of the array being deleted.
Therefore, you will have infinite recursion inside the destructor.
Then:
if (p)
delete p;
the check for p being not null (if (x) in C++ means if x != 0) is superfluous. delete does that check already.
This would be valid:
class Foo {
public:
Foo () : p(0) {}
~Foo() { delete p; }
private:
int *p;
// Handcrafting copy assignment for classes that store
// pointers is seriously non-trivial, so forbid copying:
Foo (Foo const&) = delete;
Foo& operator= (Foo const &) = delete;
};
Do not assume any builtin type, like int, float or pointer to something, to be initialized automatically, therefore, do not assume them to be 0 when not explicitly initializing them (only global variables will be zero-initialized):
8.5 Initializers: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an
object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized
So: Always initialize builtin types!
My question is how should I avoid double delete of a pointer and prevent crash.
Destructors are ought to be entered and left exactly once. Not zero times, not two times, once.
And if you have multiple places that can reach the pointer, but are unsure about when you are allowed to delete, i.e. if you find yourself bookkeeping, use a more trivial algorithm, more trivial rules, or smart-pointers, like std::shared_ptr or std::unique_ptr:
class Foo {
public:
Foo (std::shared_ptr<int> tehInt) : tehInt_(tehInt) {}
private:
std::shared_ptr<int> tehInt_;
};
int main() {
std::shared_ptr<int> tehInt;
Foo foo (tehInt);
}
You cannot assume that the pointer will be set to NULL after someone has deleted it. This is certainly the case with embarcadero C++ Builder XE. It may get set to NULL afterwards but do not use the fact that it is not to allow your code to delete it again.
You ask: "At one point, I want to de-allocate this pointer after checking whether it is valid or already de-allocated by someone."
There is no portable way in C/C++ to check if a >naked pointer< is valid or not. That's it. End of story right there. You can't do it. Again: only if you use a naked, or C-style pointer. There are other kinds of pointers that don't have that issue, so why don't use them instead!
Now the question becomes: why the heck do you insist that you should use naked pointers? Don't use naked pointers, use std::shared_ptr and std::weak_ptr appropriately, and you won't even need to worry about deleting anything. It'll get deleted automatically when the last pointer goes out of scope. Below is an example.
The example code shows that there are two object instances allocated on the heap: an integer, and a Holder. As test() returns, the returned std::auto_ptr<Holder> is not used by the caller main(). Thus the pointer gets destructed, thus deleting the instance of the Holder class. As the instance is destructed, it destructs the pointer to the instance of the integer -- the second of the two pointers that point at that integer. Then myInt gets destructed as well, and thus the last pointer alive to the integer is destroyed, and the memory is freed. Automagically and without worries.
class Holder {
std::auto_ptr<int> data;
public:
Holder(const std::auto_ptr<int> & d) : data(d) {}
}
std::auto_ptr<Holder> test() {
std::auto_ptr<int> myInt = new int;
std::auto_ptr<Holder> myHolder = new Holder(myInt);
return myHolder;
}
int main(int, char**) {
test(); // notice we don't do any deallocations!
}
Simply don't use naked pointers in C++, there's no good reason for it. It only lets you shoot yourself in the foot. Multiple times. With abandon ;)
The rough guidelines for smart pointers go as follows:
std::auto_ptr -- use when the scope is the sole owner of an object, and the lifetime of the object ends when the scope dies. Thus, if auto_ptr is a class member, it must make sense that the pointed-to object gets deletes when the instance of the class gets destroyed. Same goes for using it as an automatic variable in a function. In all other cases, don't use it.
std::shared_ptr -- its use implies ownership, potentially shared among multiple pointers. The pointed-to object's lifetime ends when the last pointer to it gets destroyed. Makes managing lifetime of objects quite trivial, but beware of circular references. If Class1 owns an instance of Class2, and that very same instance of Class2 owns the former instance of Class1, then the pointers themselves won't ever delete the classes.
std::weak_ptr -- its use implies non-ownership. It cannot be used directly, but has to be converted back to a shared_ptr before use. A weak_ptr will not prevent an object from being destroyed, so it doesn't present circular reference issues. It is otherwise safe in that you can't use it if it's dangling. It will assert or present you with a null pointer, causing an immediate segfault. Using dangling pointers is way worse, because they often appear to work.
That's in fact the main benefit of weak_ptr: with a naked C-style pointer, you'll never know if someone has deleted the object or not. A weak_ptr knows when the last shared_ptr went out of scope, and it will prevent you from using the object. You can even ask it whether it's still valid: the expired() method returns true if the object was deleted.
You should never use delete this. For two reasons, the destructor is in the process of deleting the memory and is giving you the opportunity to tidy up (release OS resources, do a delete any pointers in the object that the object has created). Secondly, the object may be on the stack.
This is merely for curiosity sake because I have not used new and delete in c++ except for the most basic uses.
I know that delete releases memory. The thing I'm wondering is how does it handle more complex cases?
For instance, if I have a user-defined class like this:
class MyClass
{
public:
MyClass();
~MyClass()
{
delete [] intArray;
}
//public members here
private:
int* intArray;
};
Assuming the class allocates memory somehow for intArray, and then release it in the destructor, What if I used the class like this: MyClass* myClass = new MyClass(); and released it later with delete myclass;
How does delete handle the releasing of all the memory? Does the class destructor get called first to release all of the memory allocated by the class (ie int* intArray) and then release the memory allocated to hold the class?
What if I had a class like this:
class MyClass
{
public:
MyClass();
~MyClass()
{
delete anotherMyClass;
}
//public members here
private:
MyClass* anotherMyClass;
};
Assuming anotherMyClass is not allocated with the constructor, which would use up memory very quickly, what if there was a chain of MyClasses attached to each other like a linked-list? Would the delete statement in the destructor work in this case? Would each anotherMyClass be recursively released when the destructor gets called?
Are there any specific weird tricks or caveats with the new and delete statements that you know about?
Given a pointer (p) to a dynamically allocated object, delete does two things:
It calls the destructor of the dynamically allocated object. Note that when ~MyClass() completes, the destructors for any member variables of class type are called.
It frees the memory occupied by the dynamically allocated object.
It doesn't search the member variables of the object for other pointers to free; it doesn't free any other memory and doesn't do anything else.
If you need to free the memory pointed to by intArray, you need to delete it in the destructor of MyClass.
However, in almost all C++ code, you don't need to worry about this. You should be using smart pointers like shared_ptr, unique_ptr, auto_ptr, and scoped_ptr to automatically manage dynamically allocated objects. Manual resource management is difficult at best and should be avoided wherever possible.
This is part of a broader idiom, Scope-Bound Resource Management (SBRM, also called Resource Acquisition is Initialization, or RAII). This is by far the most important design pattern to understand and to use everywhere in your C++ code.
If in your class you had declared this instead:
boost::scoped_ptr<int> intArray;
then when the scoped_ptr<int> object is destroyed, it will free the pointer that it holds. You then do not have to do any work to manually destroy the object.
In well-written, modern C++ code, you should rarely need to manually use delete. Smart pointers and other SBRM containers should be used to manage any type of resource that needs cleanup, including dynamically allocated objects.
In your second example, given a linked list that looks like:
x -> y -> z -> 0
you would have an order of operations that looks like this:
delete x;
x.~MyClass();
delete y;
y.~MyClass();
delete z;
z.~MyClass();
delete 0;
[free memory occupied by z]
[free memory occupied by y]
[free memory occupied by x]
The objects in the linked list would be destroyed in reverse order.
delete intArray;
I assume intArray points to the first element of an int array? In that case, delete intArray yields undefined behavior. If you allocate via new[], you must release via delete[].
delete[] intArray;
Yes I know, delete intArray might appear to work just fine on certain systems with certain compiler versions under certain compiler options -- or it might not. That's undefined behavior for ya.
Also, you should follow the Rule of Three. Defining your own destructor but relying on the implicitly-defined copy constructor and copy assignment operator is a recipe for disaster.
in the following code:
class x
{
private:
someRef& m_ref;
public:
x(someRef& someRef):m_ref(someRef)
{
}
do I need to do:
~x()
{
delete m_ref;
}
which by the way doesnt work without getting the pointer...
basically I'm asking: Do I need to call a destructor on a reference member?
No.
You only need to delete an object if you own it. If you were passed a reference, it means that someone else owns it, thus it's unnecessary and thankfully the language prevents it.
I don't think one actually strictly speaking ever deletes even pointers. What you delete are dynamically allocated objects (or arrays of objects) that the pointer is a handle for. If the object originates from a call to new and it is the responsibility of this class to clean up after this object, then you call delete.
It is technically possible that a reference might be referring to a dynamically allocated object:
int main()
{
//in principle a reference can also refer to a dynamically allocated object
x var(*new someRef);
}
//and if that is the intended usage:
x::~x()
{
delete &m_ref;
}
However, this would be incredibly bad style. By convention, the "owning" handle of a dynamically allocated object should not be a reference.
No. You can only delete pointers, not references, and even then you must only delete objects that you allocated using the new operator. And then you must be sure to delete them only once. Here is the case in which you would need to use delete in your destructor:
class x
{
private:
someObj* m_ptr;
public:
x():m_ptr(new someObj())
{
}
~x()
{
delete m_ptr;
}
But in general it's best to avoid even this and use smart pointers instead.
I want to clarify some misconceptions you seem to have that are beyond the intent of your question:
When a class's destructor is called all of it's members' destructors get called as well.
Calling delete is not the same as calling the destructor. delete explicitly calls the destructor and also calls operator delete at the objects location, it is a 2 part thing.
For a small bit of extra clarification I want to offer the following:
int *pi = new int;
//int& ir = pi; // can't do
// this a reference to the pointer but it is an error
// because or the type difference int& vs int* and
// static_cast won't help. reinterpret_cast would allow
// the assignment to take place but not help the 'delete ir'
int& ir = *pi; // this is OK - a reference to what the pointer points to.
// In other words, the the address of the int on the heap.
//delete ir; // can't do, it is a reference and you can't delete non-pointers.
delete &ir; // this works but it is still not "deleting a reference".
// The reference 'ir' is another name for the heap-based int.
// So, &ir is the address of that int, essentially a pointer.
// It is a pointer that is being used by delete, not a reference.