How to delete part of a class? - c++

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?)

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.
}
};

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 ;)

In any case, pointers are most likely the key to your desires. In any case, too, you need to separate B from MyClass, too. You can avoid a pointer within MyClass (see comments to question and other answer), if you store B separately and invert the direction of the pointer:
class MyClass
{
struct A { };
A a;
};
class Wrapper
{
struct B { };
MyClass* mc;
B b;
};
Now during initialisation, you'd create a Wrapper for each MyClass, most likely contained in two different arrays:
MyClass items[NUMBER_OF_ITEMS]; // global array?
Wrapper* wrappers = new Wrapper[NUMBER_OF_ITEMS];
// assign each item to its corresponding wrapper
// use the wrappers for initialisation
delete[] wrappers;
Now all that remains is one single pointer, of which you even might get rid if it is a local variable in a separate initialisation routine...

Related

Is it bad to recreate stack object after injected to class as pointer?

// Example program
#include <iostream>
class Foo{
public:
Foo(int a):a(a){}
void print(){
printf("%d\n",a);
}
private:
int a;
};
class Bar{
public:
Bar(Foo* foo):foo(foo){}
void print(){
foo->print();
}
private:
Foo* foo;
};
int main()
{
Foo f = {10};
Bar b(&f);
b.print();
f = {20};
b.print();
}
In the code above a Foo object shared with a Bar object can be recreated without that Bar knows about it.
Imagine I have to inject the bar object into a third class. Now I can update the foo dependency without having to create a new object of bar and the third class.
Is this pattern commonly used or not and does it violate some of the OOP principles?
I don't think the code does what you think it does.
I've added the default constructors and assign/operators to your Foo class with some logging to see what happens. These constructors are added automatically by the compilers unless you disable them explicitly. See the output here.
What happens in
f = {20};
is that you construct a different Foo object then you move-assign it to the original instance.
In this case it's equivalent to
f.a = 20; // Assuming we make a public.
In conclusion.
If your usage is just to change fields in the existing instance (through assign operators in this case). Then everything should work fine. This shouldn't necessarily invalidate OOP principles, unless you have assumptions that Bar.foo is constant or doesn't change. This is usually called composition and it's fairly common (your UI will contain various button instances that might be modified from other sources).
If you expect to change the implementation (say Foo is a virtual class and you want a different derivation to be substituted) then in your code you will need to have Foo* f = new Foo(10);. You will have copy of the pointer in b and the assignment will create a new class, that will not be update in b (something like f = new FooDerived(20);.
To make it work you need a Provider class (this is a OOP pattern). This would be something that gives you a Foo. The simplest one would be Foo**. But it's likely better to have something a bit more customizable.
That said for any serious work try to stay away from naked pointers (Foo*). Use unique_ptr or shared_ptr as appropriate to save yourself a lot of problems in the future.
Is this pattern commonly used or not and does it violate some of the OOP principles?
Yes, this is fairly common, and OK in your example.
You do have to be careful to ensure that f remains alive for the whole lifetime of b, which is the case in your example. If you were to copy b, you would also need to ensure the copy didn't outlive f.
The nice thing about the local variables of a function func is that they outlive any local variables of functions that func calls. Thus the local variables of main live for (almost) the whole program, only global variables outlive them.
Is this pattern commonly used or not and does it violate some of the OOP principles?
I would say that such a structure should be carefully used.
Actually, in Bar you are just copying the pointer value. But if the given Foo created on the stack goes out of scope, then Bar is storing a dangling pointer.
Trying to dereference a dangling pointer is Undefined Behaviour.
Is it bad to recreate stack object after injected to class as pointer?
Actually, as #DanielLangr mentioned, you did not have "recreated" the object, you just have reassigned its contents, so the object lifetime has not ended.
In your case, you're still fine.

Would an array of the same type of objects as the class it is a member of create infinite instances?

Sorry for the awkward wording of the question but I'm not sure how to describe it better in words so I'll try an example
struct A {
A* a;
A() {a = new A[2];}
~A() {delete[] a;}
}
int main() {
A aa;
}
Once aa gets constructed, the *a internal to struct A will be allocated an array of two A objects. But it appears to me that each of those objects will, in turn, create an array of A objects of their own as a result of the default constructor, and on and on in a seemingly endless cycle. Am I correct in thinking this?
Yes, you are absolutely right. Your code effectively embeds an array of objects inside itself. Essentially, you are making this impossible struct:
struct A {
A a[2]; // Impossible
};
Your code bypasses compiler's check for by using pointers, so the code crashes at runtime due to infinite recursion.
If you would like to make A that refers to two As optionally, make an array of two pointers.
Am I correct in thinking this?
Yes. The constructor is called recursively, and you'll probably run out of dynamic storage or overflowing the call stack at some point.

C++ : pointers change?

Just when I thought I was getting a good grasp of pointers, I'm confused again. Your insights will probably be helpful.
I guess I could state what confuses me in very general terms, like:
a) If I write A* p = new A(); (where A is some class), and then do stuff like (*p).do_stuff(), then the object pointed to by p might move in memory, so why would p still point to my object?
b) How are classes and member variable of classes stored in memory.
But maybe it is more useful that I tell you the problem that I have a little bit more specifically. Say I have a class Car that has a member variable Engine engine_; (where Engine is some other class). Fine. Now suppose that for some reason I want to create a class that has a member variable that is a pointer to an Engine, like:
class Car
{
friend Repair;
public:
Car() {engine_ = Engine();}
private:
Engine engine_;
};
class Repair
{
public:
Repair(const Car &car) : engine_(&(car.engine_)) {}
private:
Engine *engine_;
};
There's no chance that repair.engine_ will always point to my car's engine, is there (?) But even in this second version :
class Car
{
friend Repair;
public:
Car() {engine_ = new Engine();}
~Car() {delete engine_;}
private:
Engine *engine_;
};
// Maybe I need/should write consts somewhere, not sure
class Repair
{
public:
Repair(const Car &car) : engine_(car.engine_) {}
private:
Engine *engine_;
};
although it seems there's more chance this will work, I don't see how / understand whether it will...
Thanks in advance for your answers!
If I write A* p = new A(); (where A is some class), and then do stuff like (*p).do_stuff(), then the object pointed to by p might move in memory
No, it won't. (At least, *p will stay were it is; if it has pointer members itself, then those may get reset to point elsewhere.)
How are classes and member variable of classes stored in memory
As bits.
class Foo {
int i;
char *p;
public:
void bla();
};
will be represented as the bits of an int (probably 32) followed by those of a pointer (32 or 64), with perhaps some padding in between. The method will not take up space in your instances, it's stored separately.
As for your example, I don't exactly understand the problem. It should work if as the Car stays alive, and does not reset its Engine*, as long as the Repair object lives. (It doesn't look particularly robust, though.)
in both case 1) and case 2) there is no guarantee that repair.engine_ will always point to your car, because it's a friend class and not a member of class 'Car'
As others have said, the object does not move in memory when you do stuff like (*p).do_stuff();. You must have misunderstood something that you learned at some point.
For your second question, member functions and member variables are stored in different places in memory. The code for member functions is only generated once for each class, not once for each instance of the class. This code is stored at some location in memory.
As for member variables, this is what people are talking about when they mention your object's location in memory. For example, if you have a class like
class MyClass{
private:
int a;
int b;
double c;
public:
void fun();
};
and we assume that an instance of it is stored at memory location 0x0000, this means that a is at location 0x0000, b is at 0x0004, and c would be at 0x0008 (or something like this depending on how memory is laid out). The function fun() is stored somewhere else entirely.
Now if we make another instance of MyClass, it's a variable might be at 0x000C, it's b might be at 0x0010, and it's c at 0x0014. Finally, it's fun() is in the exact same location as fun() from the first instance.
Pointers in C++ allocated with new don't move. You might be thinking of malloc, where a pointer can be realloc'd and possibly go to a new location as a result.
Bjarne Stroustrup felt that C++ containers generally provided a better way to deal with the wish to have dynamically sized memory:
http://www2.research.att.com/~bs/bs_faq2.html#renew
In order to allow for movement and reorganization of memory, some systems use abstract handles that need to be locked into pointers before you can use them...such as Windows:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366584(v=vs.85).aspx
Using something abstract which you lock into pointers might make sense in a system that needs to do some kind of periodic memory defragmentation. But C++ doesn't pay the cost for that indirection by default, you'd implement it only in cases where it makes sense to do so.
(On the downside, with non-movable pointers if you allocate a million objects and then delete 999,999 of them... that one object which is left may stay sitting way up at the top of the address space. The OS/paging system is supposed to be smarter than to let this be a problem, but if your allocator is custom this might leave your heap at a big size. For instance: if you're using a memory-mapped file as a backing store for your objects...you'll be stuck with a large and mostly empty disk file.)

Size of class instance

I'm working with a class for which the new operator has been made private, so that the only way to get an instance is to write
Foo foo = Foo()
Writing
Foo* foo = new Foo()
does not work.
But because I really want a pointer to it, I simulate that with the following :
Foo* foo = (Foo*)malloc(sizeof(Foo));
*foo = Foo();
so that can test whether the pointer is null to know whether is has already been initialized.
It looks like it works, from empirical tests, but is it possible that not enough space had been allocated by malloc ? Or that something else gets funny ?
--- edit ---
A didn't mention the context because I was not actually sure about why they the new operator was disabled. This class is part of a constraint programming library (gecode), and I thought it may be disabled in order to enforced the documented way of specifying a model.
I didn't know about the Concrete Data Type idiom, which looks like a more plausible reason.
That allocation scheme may be fine when specifying a standard model --- in which everything is specified as CDTs in the Space-derived class --- but in my case, these instance are each created by specific classes and then passed by reference to the constructor of the class that reprensents the model.
About the reason i'm not using the
Foo f;
Foo *pf = &f;
it would be like doing case 1 below, which throws a "returning reference to local variable" warning
int& f() { int a=5; return a; } // case 1
int& f() { int a=5; int* ap=&a; return *ap; }
int& f() { int* ap=(int*)malloc(sizeof(int)); *ap=5; return *ap; }
this warning disappears when adding a pointer in case 2, but I guess it is because the compiler loses tracks.
So the only option left is case 3 (not mentioning that additionaly, ap is a member of a class that will be initialized only once when f is called, will be null otherwise, and is the only function returning a reference to it. That way, I am sure that ap in this case when lose its meaning because of the compilier optimizing it away (may that happen ?)
But I guess this reaches far too much beyond the scope of the original question now...
Don't use malloc with C++ classes. malloc is different from new in the very important respect that new calls the class' constructor, but malloc does not.
You can get a pointer in a couple ways, but first ask yourself why? Are you trying to dynamically allocate the object? Are you trying to pass pointers around to other functions?
If you're passing pointers around, you may be better off passing references instead:
void DoSomething(Foo& my_foo)
{
my_foo.do_it();
}
If you really need a pointer (maybe because you can't change the implementation of DoSomething), then you can simply take the pointer to an automatic:
Foo foo;
DoSomething(&foo);
If you need to dynamically allocate the Foo object, things get a little trickier. Someone made the new operation private for a reason. Probably a very good reason. There may be a factory method on Foo like:
class Foo
{
public:
static Foo* MakeFoo();
private:
};
..in which case you should call that. Otherwise you're going to have to edit the implementation of Foo itself, and that might not be easy or a good thing to do.
Be careful about breaking the Concrete Data Type idiom.
You are trying to circumvent the fact that the new operator has been made private, i.e. the Concrete Data Type idiom/pattern. The new operator was probably made private for specific reasons, e.g. another part of the design may depend on this restriction. Trying to get around this to dynamically allocate an instance of the class is trying to circumvent the design and may cause other problems or other unexpected behavior. I wouldn't suggest trying to circumvent this without studying the code thoroughly to ensure you understand the impact to other parts of the class/code.
Concrete Data Type
http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#ConcreteDataType
Solutions
...
Objects that represent abstractions that live "inside" the program, closely tied to the computational model, the implementation, or the programming language, should be declared as local (automatic or static) instances or as member instances. Collection classes (string, list, set) are examples of this kind of abstraction (though they may use heap data, they themselves are not heap objects). They are concrete data types--they aren't "abstract," but are as concrete as int and double.
class ScopedLock
{
private:
static void * operator new (unsigned int size); // Disallow dynamic allocation
static void * operator new (unsigned int size, void * mem); // Disallow placement new as well.
};
int main (void)
{
ScopedLock s; // Allowed
ScopedLock * sl = new ScopedLock (); // Standard new and nothrow new are not allowed.
void * buf = ::operator new (sizeof (ScopedLock));
ScopedLock * s2 = new(buf) ScopedLock; // Placement new is also not allowed
}
ScopedLock object can't be allocated dynamically with standard uses of new operator, nothrow new, and the placement new.
The funny thing that would happen results from the constructor not being called for *foo. It will only work if it is a POD (simple built-in types for members + no constructor). Otherwise, when using assignment, it may not work out right, if the left-hand side is not already a valid instance of the class.
It seems, you can still validly allocate an instance on the heap with
Foo* p = ::new Foo;
To restrict how a class instance can be created, you will probably be better off declaring the constructor(s) private and only allow factory functions call them.
Wrap it:
struct FooHolder {
Foo foo;
operator Foo*() { return &foo; }
};
I don't have full understanding of the underlying code. If other things are ok, the code above is correct. Enough space will be allocated from malloc() and anything funny will not happen. But avoid using strange code and work straighforward:
Foo f;
Foo *pf = &f;

How to reassign `this` pointer inside object member function?

I have an interesting question about C++ pointers.
You probably will think that I have to change my design, and avoid
doing what I am doing, and you are probably right.
But let's assume that I have a good reason to do it my way.
So this is the situation. I have a C++ class TestClass, and I have a pointer A of this type:
TestClass* A = new TestClass();
Among other things TestClass has this function:
void TestClass::Foo(){
TestClass* B = new TestClass();
...
}
This function creates object B of the same type and populates it with some data.
At the end of this function, I want pointer A to point at object B.
Anywhere outside this function it would look like A=B; inside this function
it could look like this = B
But as you know you cannot reassign "this" pointer.
Possible solutions:
Copy the memory:
memcpy(this, B, sizeof(TestClass));
This method works correctly. The function copies each bit of object B into object A.
Problem: if TestClass is a big object(and it is), it creates significant overhead in performance for multiple Foo calls.
Return a B pointer from the function and do something like this
Temp = A;
A=A->Foo();
freeMemory(Temp);
But this code looks stupid, and it makes function Foo very hard to use.
So the question is, how I can do this = B from inside a member function, without copying whole objects?
Use an extra level of indirection. Your TestClass can have a pointer that points to a class that contains all of its data.
class TestClass
{
private:
TestClassData* m_data;
};
void TestClass::Foo()
{
TestClassData* B = new TestClassData();
...
delete m_data;
m_data = B;
}
Just make sure your operator== returns true if the contents of m_data are equal.
how i can do this = B
You cannot.
One of the working solutions:
memcpy(this, B, sizeof(TestClass));
this method working correctly.
If TestClass is not a POD, this function doesn't work. You can't memcpy objects with virtual functions, for example. You'll blow away the vtable.
Inside of your function, you can do
*this = B;
Which make pretty the same copy operation.
Or you could also declare
Foo(TestClass &X);
And reassign X address inside.
You can't. this is defined by the standard as a TestClass * const.
To realize why, think about this code:
int main() {
TestClass A;
A.Foo();
return 0;
}
A is on the stack. How do you make an object on the stack 'refer' to something else?
The problem is that many pointers, not just A, can point to the old object. The this pointer is not A, although A contains a copy of it. The only way to do it is 1. reassign A, or 2. make a new pointer type that adds a level of indirection to your object so you can replace it without anyone knowing.
What you are doing is not good.
First off, you have function Foo that will:
Create and generate a new class
Reassign an existing class to the new class
So, why not just change the existing class into the class you want?
That said, you could make Foo static and take "take this manually":
void Foo(TestClass*& this)
{
delete this;
this = // ...
}
But that's equally nasty as your other solutions. We probably need more context to give you the best solution.
I'm pretty sure that you should look at smart pointers as a way to solve this problem. These essentially add an extra level of indirection (without changing the syntax clients use), and would allow you so change the actual object pointed to without informing the client.