There are other classes in the Standard C++ library for managing pointers besides std::unique_ptr. Check out std::shared_ptr and std::weak_ptr.
I want that if an object is deleted then all the pointers to it are set to nullptr, or something like that
Edit: I realized that I can compare pointers with the operator==, and I explain it in a post at bottom.
#include "stdafx.h"
#include <conio.h>
typedef unsigned long long UniqueId; // The reason it's 64-bit is a memory block can be freed and reallocated multiple times, which means that there can be a lot of ids.
UniqueId newUniqueId() {
static UniqueId id = 0;
return id++;
}
// Edit: Wrong-lesson: Never compare pointers using of the operator== because a pointer can be not unique,
// for example a deleted object and re-created object can have the same pointer, but use unique id.
bool areSame(GuiObject *obj1, GuiObject *obj2) {
if ((obj1 != nullptr) && (obj2 == nullptr)) { return false; }
if ((obj1 == nullptr) && (obj2 != nullptr)) { return false; }
if ((obj1 == nullptr) && (obj2 == nullptr)) { return true; }
if (obj1->_id == obj2->_id) { return true; }
return false;
}
6 additional answers
Sort by: Most helpful
-
RLWA32 43,381 Reputation points
2022-03-19T12:55:01.66+00:00 Change the MyObject == operator method to take a reference
bool operator==(const MyObject& obj) const { return _id == obj._id; }
Then you can use dereferenced pointers in your comparison -
bool cmp1 = (*a == *b);
-
Manda Rajo 141 Reputation points
2022-03-19T15:00:03.033+00:00 Ok, I was replacing all the operator== on GuiObject * with areSame(), and I realize that I don't need to do that, it's ok to compare pointers with ==, let me explain.
RLWA32-6355 > its your responsibility to set them to nullptr after calling delete
void MyClass::func(GuiObject *obj1) { // this->internal_obj2 was copied to the class MyClass from outside and if it's deleted outside then it's not changed to nullptr. EMC_CHECKEXISTENCE(this->internal_obj2); // The solution must be like this, the internal_obj2 must be a "dynamic var" or "variant", which means that if it's deleted somewhere else then this code cannot even reached, so no need to use areSame. if (obj1 == this->internal_obj2) { // This is ok because suppose that obj2 or internal_obj2 was accidentally deleted outside, and this line cannot even reached. printf("They are same"); } }
The reason I use the prefix "internal_" is as a warning, so when I read it, which means that it can be deleted outside but cannot be automatically set to nullptr internally.
So, my new question is: "Does anyone has a suggestion? Because I don't know what is that dynamic variable in C++ I was talking about".
-
Manda Rajo 141 Reputation points
2022-03-20T07:17:30.567+00:00 Myself > Ok, thank you so much, I'm studying std::shared_ptr and std::weak_ptr. I believe that it's the solution of my problem.
Example: https://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful
The reason I re-post the answer, is the comment sections are almost hidden inside tiny buttons (Show), and what if in a very far future, no body knows, when I will come back to visit this thread, then will I see the answers?
-
Manda Rajo 141 Reputation points
2022-03-19T11:56:02.343+00:00 RLWA32-6355 > So what are you trying to accomplish?
The worst crash with a program made with C++ is always about "Pointers & Destruction", "Memory Leak", and the worst is about Destruction because it causes crash, and sometimes, crash that impossible to detect.
I want to build a user interface (GUI) with so many objects in hierarchy (parents, and children, and linked objects with each other by using of pointers instead of strings because pointers are fast). I will use strings when performance is not required. What I want is when I delete an object then it sends signals to all the other objects linked to that deleted object, so the other objects will do actions of deleting too.
The code of hovering a menu item looks like this, but this is still in development, it's not stable.
void TooltipManager::hoverObject(GuiObject *object) { EMC_DEBUG_DISPLAYFLAGS(g_debug_displayFlags_tooltipManager); if (areSame(object, _.internal_hoveredObject)) { // <-- Good practice, I'm not using the operator== to compare pointers. return; } _.internal_hoveredObject = object; //-------------------------------------------------- if (_.tick_isStarted == false) { this->startTick(debug_displayFlags); } if (_.tooltip_isBegan == true) { this->updateTooltip(debug_displayFlags); } }
How I delete an object by showing warning if a parent object is deleted before deleting its child object:
enum DoesExist { DoesExist_No = 0x87654321, // DoesExist_Yes = 0x12345678, // The reason of not using a boolean is for safe reason because when a memory is deleted then it becomes a random number. }; #define EMC_CHECKEXISTENCE(obj) { \ EMC_VERIFY(obj != nullptr && "Don't use a nullptr."); \ EMC_VERIFY(obj->_existence == DoesExist_Yes && "Don't delete the parent object before deleting its child object, or maybe the object is just deleted when trying to use its pointer."); \ } ((void)0) // There must be ";". GuiObject::~GuiObject() { _existence = DoesExist_No; // Delete the object from its parent if (_x.parent != nullptr) { // A window object doesn't have a parent object. EMC_CHECKEXISTENCE(_x.parent); // A line like this shouldn't be evaluated if the parent doesn't exist because it makes a pointer to a deleted memory. std::vector<GuiObject *> &vec = _x.parent->_x.objects; for (int i = 0; i < vec.size(); i++) { if (vec[i] == this) { // WARNING: I find in the entire project about "==" then I found this bad practice, both are GuiObject *, I should write areSame(vec[i], this). vec.erase(vec.begin() + i); break; } } } }
And another:
GuiObject *obj = p->getLastObject(); if (obj == this) { // WARNING: I should write: areSame(obj, this). ... }
And there are a lot of of using of the operator == every where, bad old practice, I must replace them all with areSame().