Reputation: 33
I'm trying to realize a smart pointer by myself. I know that I can use smart pointers instead of this but I'm trying to do this only for understanding smart pointers structure.
Тhe problem is the following when my smart pointer has been starting to call the destructor, this is checking if my pointer is not nullptr
then if it is true this will delete ptr.
After this when the destructor has been calling again for CastS I'm getting an exception because the destructor is trying to delete an already deleted element and my if statement for the second time isn't working (as I was expecting) because after the deletion of an element the address is changing and the pointer isn't null anymore.
How Can I improve this code and how can I not delete twice already deleted pointer?
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <memory>
using std::cout;
using std::endl;
template<typename T>
class Smart_Pointer
{
private:
T* ptr;
public:
Smart_Pointer(T* ptr);
~Smart_Pointer();
T& operator*();
};
template<typename T>
Smart_Pointer<T>::Smart_Pointer(T* ptr)
{
this->ptr = ptr;
}
template<typename T>
Smart_Pointer<T>::~Smart_Pointer()
{
if (ptr != nullptr)
{
delete ptr;
ptr = nullptr;
}
}
template<typename T>
T& Smart_Pointer<T>::operator*()
{
return *ptr;
}
int main()
{
Smart_Pointer<int> castS(new int(10));
Smart_Pointer<int> castS2 = castS;
}
Upvotes: 0
Views: 191
Reputation: 16119
How Can I delete all pointers to the same address?
First problem is that you don't know how many points to the same address.
This can be solved in many ways.
The counter should be atomic if you intent to do multi-threading.
Implementing an external free counter has the huge advantage that you don't have the indirection of 1. and don't have the intrusiveness of 2 nor the complexity of GC.
Untested code
std::unordered_map<void *, std::atomic_int> extro_count;
You then need to implement the rule of 3 or rule of 5 depending on how advanced you want to make it.
template<typename T>
Smart_Pointer<T>::~Smart_Pointer() {
if (ptr != nullptr) {
if (--extro_count[ptr] == 0) {
extro_count.erase(ptr);
delete ptr;
ptr = nullptr;
}
}
I leave the implementation of the others to the OP.
This is still very unsafe in threaded code unless your careful.
Upvotes: 0
Reputation: 40882
Smart Pointer is an umbrella term. For the std library it describes unique_ptr
, shared_ptr
and weak_ptr
.
If you want to implement a unique ptr you need to ensure that only one unique ptr owns the raw pointer, so you need to delete the copy constructor and copy assignment operator. To be able to transfer ownership between your unique pointers you have to provide move constructor and move assignment operator in a way that the ownership is transferred.
If you want to implement a shared ptr you need to implement reference counting.
How Can I delete all pointers to the same address? C++
That's something you don't want to do, you want to keep the managed object alive as long as there is at least one shared pointer owning that managed object.
Rule of three: If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.
Rule of five: Because the presence of a user-defined destructor, copy-constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator, any class for which move semantics are desirable, has to declare all five special member functions:
Upvotes: 2
Reputation: 1
How Can I delete all pointers to the same address? C++
You probably cannot do that reliably and automatically. Be aware of Rice's theorem, and read more about programming in C++, then see this C++ reference. Understand that pointers are organizing your virtual address space as some directed graph which evolves during the execution of your program.
Maybe you want to clear all pointers to the same address.
For example, read the GC handbook.
Consider using some static analysis tool on your C++ source code, e.g. the Clang static analyzer.
Consider also generating some your C++ code (like SWIG or GNU bison does). You might code your generator of C++ code (e.g. using GPP or GNU m4, or your own generator of C++ files) to ease the management of your pointers.
Read also n3337 (some draft C++ standard) and the documentation of your C++ compiler (perhaps GCC).
Be aware that reference counting has drawbacks (e.g. it is not multi-thread friendly).
Study for inspiration the source code of existing C++ open source programs (e.g. on github), such as Fish, Qt, RefPerSys, GCC, Clang, ANTLR. Consider contributing to one of them.
Upvotes: 1
Reputation: 181
If you are trying to emulate the behaviour of unique_ptr, this is solved by simply not allowing copy. If you delete the copy constructor, no two smart pointers can be pointing to the same address at the same time. You simply write:
SmartPtr(const SmartPtr&) = delete;
However, if you do this you might want a way to transfer ownership, so it would be nice to implement a move constructor:
SmartPtr(SmartPtr&& other) {
ptr = std::exchange(other.ptr, nullptr);
}
Or something like that. If you really want to allow two smart pointers to point to the same address, you need a way to decide which one is going to delete the ptr, usually the last one that goes out of scope. The way this is done in the standard (eg. In shared_ptr) is by defining a shared structure between all instances of the class, but that's probably way out of the scope of this answer..
Upvotes: 0