Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete part of a class?

Tags:

c++

oop

The problem is quite simple. I have a class that can be structured as the following:

class MyClass {
  struct A {
    // ...
  };
  struct B {
    // ...
  };
};

The problem is: the information in MyClass::B is useless after some time of precomputations, whereas MyClass::A must never be deleted (the program may be running for days). MyClass::B holds quite a large amount of information. I want to get rid of MyClass::B while keeping MyClass::A in the same memory position.

Is it possible to do this without modifying too much the data structure and not having to add anything else to MyClass::A (in particular, a pointer to MyClass::B)? If so, what would be the right way to implement it? Take in account that the program must be as memory-efficient as possible (and let us take that to the extreme). I use C++14 BTW.

(And extra question: It is possible to delete the chunk corresponding to MyClass::B from MyClass?)

like image 640
Victor Martin Avatar asked Nov 17 '25 08:11

Victor Martin


2 Answers

First or all that's a class declaration. You can't delete a part of the class declaration. You probably have something more like this:

// The exact place of the declaration doesn't matter actually
class A {...}; 
class B {...};

class C {
    A a;
    B b;
}; 

Just change it to use a pointer (in this day and age a smart pointer, like std::unique_ptr):

class C {
    A a;
    std::unique_ptr<B> b;

    void FinishTaskThatRequiredB() {
        b.reset(); // calls B::~B() and frees the memory.
    }
}; 
like image 62
churill Avatar answered Nov 18 '25 22:11

churill


Okay, let's elaborate a bit on what I wrote: “either the life of B is tied to that of MyClass, or it is independent. In that latter case, you must keep track of it in some way”.

Putting the context back from the question:

  • MyClass::B is useless after some time of precomputations.
  • MyClass::A must never be deleted.

Is ensues that you want to keep track of it in some way. How? Well, that depends on the rules on the life time.

  • If B could sometimes exist and sometimes not depending on hard to control (or plain unknowable) circumstances, then having a pointer to it, set to nullptr when it is useless, and dynamically allocated when it is useful is pretty much the only solution.

But here we have more knowledge: B exists first, then becomes useless and remains so forever. In other terms, you don't need B after some initial building steps used to create A.

There is a pattern that does exactly this: the builder pattern. Its purpose is to encapsulate a complex building operation, maybe tracking some state, until it has built some object, at which point it becomes useless and can be destroyed.

class ABuilder
{
public:
    setSomeInfo(int);
    doSomeComputation(......);
    // etc

    A get();    /// finalize building of A

private:
    int someInfo_ = 0;
};

// somewhere else
auto b = ABuilder();
b.setSomeInfo(42);
b.doSomeComputation(......);

auto a = b.get();
// b is no longer used past that point
// delete it if it was allocated dynamically
// or let it go out of scope if it was automatic

From your example, it would map somewhat like this:

  • A is still A.
  • B is ABuilder.
  • MyClass is not needed.

If you had provided actual class names and purpose, it would have been easier to make the examples meaningful ;)

like image 22
spectras Avatar answered Nov 18 '25 22:11

spectras