tags:

views:

238

answers:

7

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:

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

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

+5  A: 

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.

John Dibling
The vtable pointer isn't much of a problem (since it's immutable for a concrete type), but any other reference that needs special handling is - more generally, anything that needs a Copy CTor (considering the "if you need one, you need all three" rule).
peterchen
+2  A: 

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.

Richard Pennington
A: 

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.

Alex Brown
+3  A: 

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?

Nick Meyer
+10  A: 

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.

Bill
This I think is the most elegant way to do it if your goal is to minimize data copying.
Tyler McHenry
"Any problem in computer science can be solved by adding another layer of abstraction" --(wish I could remember where I'd seen that)
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner: <http://www2.research.att.com/~bs/bs_faq.html#really-say-that>. Stroustrup is widely believed to have said it, but he quoted David J. Wheeler.
unwind
Nice... like an implementation of object String with an internal char[] buffer. I like it.
helios
+1  A: 

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.

GMan
+2  A: 

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.

alemjerus