How to reassign `this` pointer inside object member function? - c++

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.

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.

How to delete part of a class?

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

Parameter-passing of C++ objects with dynamically allocated memory

I'm new to the C++ world, but I have some experience with C and read some tutorials about C++.
Now, creating objects in C++ seems quite easy and works well for me as long as the class has only attributes that are values (not pointers).
Now, when I try to create objects which allocate memory in the constructor for some of their attributes, I figure out how exactly such objects are passed between functions.
A simple example of such class would be:
class A {
int *a;
public:
A(int value) {
this->a = new int;
*(this->a) = value;
}
~A() {
delete this->a;
}
int getValue() const { return this->a; }
}
I want to use the class and pass it by value to other functions, etc. At least these examples must work without creating memory leaks or double free errors.
A f1() {
// some function that returns A
A value(5);
// ...
return value;
}
void f2(A a) {
// takes A as a parameter
// ...
}
A a = f1();
A b = a;
f2(a);
f2(f1());
The class A is incomplete because I should override operator= and A(A& oldValue) to solve some of these problems.
As I understand it, the default implementation of these methods just copy the value of the members which is causing the destructor to be called twice on the same pointer values.
Am I right and what else am I missing?
In addition, do you know any good tutorial that explains this issue?
Use containers and smart pointers.
E.g. std::vector for dynamic length array, or boost::shared_ptr for dynamically allocated single object.
Don't deal directly with object lifetime management.
Cheers & hth.,
When you pass an object like that, you will create a copy of the object. To avoid doing that, you should pass a const reference...
void f2(A const & a)
{
}
This does mean that you are not allowed to change 'a' in your function - but, to be honest, you shouldn't be doing that anyways, as any changes won't be reflected back to the original parameter that was passed in. So, here the compiler is helping you out, but not compiling when you would have made a hard to find error.
Specifically, you must implement a copy constructor that properly copies the memory pointer for the a variable. Any default constructor would simply copy the memory location for the a variable, which would obviously be subject to a double-delete.
Even doing this:
A value(5);
// ...
return value;
won't work because when A falls out of scope (at the end of the section) the delete operator for A will be called, thus deleting the a sub-variable and making the memory invalid.

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 make object pointer NULL without setting it explicitly, without deleting explicitly and without static functions?

I am working on a c++ application.
In my code i have an object pointer like
TestClass *pObj = new TestClass();
and Member function call like pObj->close();
Inside close() member function, i should make pObj to NULL.
As per our requirement, TestClass users should not call delete on pObj.(Destructor of TestClass is made private intentionally for this purpose)
Also, TestClass should not expose any static method to receive a pointer and making it NULL.
Is there any other way to make pObj to NULL once close() is called ?
I tried one way.
Inside close() function, i removed constness for this pointer using const_cast.
and took a reference of it.
Then i made this = NULL.
Even then calling side, pObj pointer value remains. It is not getting set to NULL.
It may be due to the Address of this pointer and Address of pObj are different.
Pls help.
EDIT: Sorry, i missed something. new is getting called inside a static function called init. init function is like below. void init(TestClass *& pObj); So TestClass user calls init first for allocation. But he can't call deinit(there should not be any such function) Actually, this is not my design. It was present when i entered this project :(
Imagine such code:
TestClass *ptr1 = new TestClass();
TestClass *ptr2 = ptr1;
ptr2->close();
Which pointer do you want to be set to null? Inside close method you have no information how many pointers point to your object and how is close method accessed.
There's no way of doing what you want, given your constraints.
One warning: what happens if the user of your class creates on object on the stack: TestClass test;?
One question more, why do you want the users of your class being forced to call new to allocate objects of your class, but then being forbid to call delete. Makes no sense to me.
An insane problem requires an insane solution, so here is one. You can't do exactly what you want, since it's impossible to keep track of the raw pointers to your object. However, if you use some kind of smart pointer, then they can be tracked and nullified when the object is destroyed. This is a common requirement in less insane circumstances, so there are already smart pointers to do this: shared_ptr to keep the object alive, and weak_ptr to track the object and go null when it's destroyed. So the solution would look something like this:
class TestClass
{
public:
static weak_ptr<TestClass> create()
{
shared_ptr<TestClass> shared(new TestClass);
shared->self = shared;
return shared;
}
void close()
{
self.reset();
}
private:
shared_ptr<TestClass> self;
};
int main()
{
weak_ptr<TestClass> object = TestClass::create();
weak_ptr<TestClass> copy = object;
assert(!object.expired());
assert(!copy.expired());
object.lock()->close();
assert(object.expired());
assert(copy.expired());
}
As per our requirement, TestClass users should not call delete on pObj.(Destructor of TestClass is made private intentionally for this purpose) Also, TestClass should not expose any static method to receive a pointer and making it NULL.
Who set those requirements? For each of them, ask "Why?". They seem absolutely arbitrary, they make no sense.
and Member function call like pObj->close(); Inside close() member function, i should make pObj to NULL.
Again, "Why?". Disregarding changing this from inside of a function is not possible, using such style is crazy. A normal C++ way is to destruct the object instead.
If you will get no reasonable answer to your "whys", you should probably consider quitting the job, or prepare to spend your time there in frustration. The design "requirements" you have presented are really extraordinary crazy.
No. Consider the following code:
TestClass * const pObj = new TestClass();
pObj->close();
The compiler will not reject the code, even if close would be const. The pointer is const, but not the new TestClass object. Therefore you can call non-const methods via the pointer, but you can't change the pointer itself. That means you can't set it to NULL either.
It basically means that you need to set this pointer to NULL. This is not possible as far as I know. If it helps you can think the calling of the method taking this pointer by value i.e. whatever change you do inside the method will not be reflected outside.
while you're writing terrible code you may as well add some inline assembly and xor ecx,ecx just before you return from close().
Probably won't work unless you happen to be super careful with the pObj init returns to not to anything fancy with it.
#include <map>
std::map<TestClass*, TestClass**> pointers();
void init(TestClass *& pObj)
{
pObj = new TestClass();
pointers[pObj] = &pObj;
}
void TestClass::Close()
{
*pointers[this] = null;
pointers.erase(this);
delete this;
}
Though, it is full of dangers, a way could be
TestClass::Close(Testclass *&p){
p = NULL;
}
pObj->close(pObj);
EDIT: After explanation on restriction of Close();
Is pObj accessible in scope of 'TestClass::Close'? e.g. a namespace scope variable?
If yes, the TestClass::Close method can simply set pObj = NULL;
If no, there is no way IMHO