1

I would like to use the same variable but I want to reinstantiate it. How do I do it in c++? Here is a simple example. I try to reinstantiate t1 but it doesn't compile. (Notice t1 is stored in the stack. I'm not asking how to do dynamic memory allocation)

class Table
{
  private int feet;
  public Table(int x)
  {
    feet=x;
  }
}

Table t1(3);
t1(4);
Kaimde
  • 13
  • 3

4 Answers4

8

The answer is a wonderful language feature called assignment.

In short, you can change the value of a variable – even a variable of a type you have defined yourself – by using the = symbol.

As a matter of fact your code is already using assignment, namely in the constructor.

In the example below I've replaced that original code's assignment with an initializer, because initializers are generally preferable (choose them when there is no good reason to use assignment for initializating members).

The assignment that updates the value of t1, effectively "reusing" t1, can go like this:

class Table
{
private:
    int feet;
public:
    Table( int x ): feet( x ) {}
};

Table t1( 3 );
t1 = Table( 4 );

Note 1: it's possible to define a type so that assignment is prohibited.

Note 2: since you have defined a conversion constructor, one that accepts a single argument, and since that constructor is not explicit, the assignment above can be expressed more simply (but perhaps less clearly) as …

t1 = 4;

… which results in exactly the same.

Note 3: your code as presented would not have compiled, it was just "like" C++, it was not C++. I've fixed the errors (I think, but I didn't bother to run it through a compiler). But in general it's not always possible to know or even guess whether errors in the presented code have something to do with the question, so please copy and paste real code.

Cheers & hth.,

Cheers and hth. - Alf
  • 135,616
  • 15
  • 192
  • 304
  • I like this answer. :) +1 from me. – Prasoon Saurav Dec 05 '10 at 04:30
  • 1
    I'm going to go out on a limb and guess that the real code is much more complicated than the snippet shown, in which case the compiler-provided assignment operator may not be adequate, and a user-defined assignment operator may end up duplicating much of the Table destructor and constructor code. That's where swap would be helpful, to eliminate that code duplication, and also provide exception safety. – Ben Voigt Dec 05 '10 at 04:39
  • +1 just for getting the response you did from Kaimde... hilarious. :-) – Tony Delroy Mar 03 '11 at 07:43
  • I know this Question is old but I'm quite new to C++ as well. In your Answer what happens with the Memory of the old Object? Does it get freed or do we have to free it? – Arne Fischer Apr 16 '14 at 09:44
  • 1
    @ArneFischer: For the code in the answer `t1` is a variable with *automatic* storage duration. In practical terms, with most any C++ implementation this means it's allocated on the machine stack, extremely efficiently (it's just an adjustment of the stack pointer), and automatically deallocated when the execution leaves the block where the definition is (also extremely efficiently). Its memory contents are just changed by the assignment: there is no further allocation for the variable/value. So you don't have to free anything. – Cheers and hth. - Alf Apr 16 '14 at 13:30
  • Ok I got that. Thanks a lot! – Arne Fischer Apr 17 '14 at 07:19
2

I'd suggest using the swap idiom instead, but if you really want to recreate a new object in the same variable, use placement new:

Table t1(3);
t1.~Table();
new (&t1) Table(4);

Placement new simply constructs an object in memory you provide, without doing any allocation.

If you decide to go with swap, you'll have to write the swap function, and then to do the reinstantiation:

Table t1(3);
Table(4).swap(t1);
Community
  • 1
  • 1
Ben Voigt
  • 260,885
  • 36
  • 380
  • 671
  • 6
    This is an extremely dangerous technique. It's not something to suggest to an utter newbie. – Cheers and hth. - Alf Dec 05 '10 at 04:14
  • @Alf: That's why my answer starts out suggesting a simpler way. – Ben Voigt Dec 05 '10 at 04:19
  • @Alf: Could you explain what is dangerous about it? – Kaimde Dec 05 '10 at 04:19
  • @Kaimde: I added a link to a great discussion of swap by GMan and some other experts. I really would suggest you check that out first, before using placement new. – Ben Voigt Dec 05 '10 at 04:27
  • 3
    @Kaimde: I should mention, what you're looking for here is a little different from copy-and-swap, since you'll be creating a brand new object to swap in. But all the explanation about separation of construction and destruction, and only doing the teardown if the replacement construction succeeds, apply to your case. That's one of the dangers of placement new, actually: If `new (&t1) Table(4);` throws an exception, because the compiler successfully constructed `Table t1(3);`, it will destroy it during unwind... but you destroyed it too. Double free is never fun. – Ben Voigt Dec 05 '10 at 04:34
0

Why do you want to reinstanciate ? That's not RAII.

Instanciation is about getting space for object, then calling constructor. If you just want to change the member values, or call some method, create some init method and call it both from constructor and when you want to reset object. This works in simple cases bus is not exactly like a constructor. Some things (like initializing reference members) can be done only in initialization list that exists only in constructor.

And obviously you should take some care, as destructors should be called for member variables before reallocating them.

Placement new would also works, but it looks like overkill, you won't get more with it than through calling a simple method to reset object. And it's dangerous as it can lead to very tricky bugs.

SWAP Idiom as suggested by Ben Voight is probably the best choice you have if you go on the overloading of assignement operator track.

My advice on reinstanciating is don't.

What's the problem with using a brand new instance and leaving the old one alone ? Reusing the same variables for different tasks was already a bad idea with C as it makes compiler optimization harder. It still is with C++, and it is also dangerous as you may easily forget to call destructor of the first object and go into troubles.

There is cases where you would need to do that, like if you took the address of the object, and want to change it's members. But in such cases it's probably better to change your code to avoid doing that anyway. I can see of no real case where this would be necessary. If there is, I'm interested to know about.

kriss
  • 21,366
  • 15
  • 89
  • 109
  • 1
    Not all C++ classes are RAII, because not all C++ classes manage resources. – Ben Voigt Dec 05 '10 at 04:20
  • Furthermore, the *ctor-initializer-list* only works inside the constructor, not some init method it delegates to. – Ben Voigt Dec 05 '10 at 04:26
  • Yes, you can't simulate ctor initializer list, and if you use reference members what I propose won't be enough. I will edit my answer. – kriss Dec 05 '10 at 07:33
0

The prefered answer doesn't solve the problem quite well. The assignment doesn't actually reinstantiate the object, it just does an assignment. In the example, if feet were to be const, the solution won't compile.

A trickier solution would be use "Placement new"/"Placement syntax" like:

Table t1(3);
t1.~Table();
new (&t1) Table(4);