0

C++: can the object be destroyed earlier, to make its storage memory be reused by subsequent objects?

In one segment of C++ code, at the 1st half part, objects a, b are used; at the 2nd half part, objects c, d are created and used.

Since objects a, b take a lot of memory, I want to manually destroy objects a, b when the 1st half part finishes.

I know I can use new, delete to achieve it.

But if I do not use new, and still want to destroy objects earlier (that means, before the time of its end of scope), can I manually call its destructor to destroy it? So that part of memory can be reused for object c and d. (I do not need to release the memory since reuse is fine.

Here is a pseudo code:

monsterClass a, b;
dragonClass c, d;
int i,j,k,l;

a = monsterClass(1000, 2000);
b = monsterClass(2000, 3000);
i = processMethod1(a, b);
j = ...;
k = ...;
l = ...;


// here, I want to destroy a, b, since they are not used any more, while occupy memory.
// The above half part and the below half part use many common variables. 
// So it seems scope {} method makes it inconvenient, 
// since I don't want to create a function with too many parameters.
// I don't want to use new or delete here. I hope it looks simple and not prone to error
// So can I use: ~a, ~b here?

c = dragonClass(400, 3000);
d = dragonClass(500, 4000);
processMethod2(c, d, i);
j = ...;
k = ...;
l = ...;

[Update 1] So most people suggest to use scope, which is a good way. I am just still very curious, can I use ~a and ~b there? I think it seems to be a feasible and convenient way, too.

[Update 2] I come up another situation. In this situation, the scopes of different variables are interwined! It is like this: the scope of a has an overlap of scope of b, but they are not including relationship. It is overlap partly relationship. In this case, does this mean using scope is not possible? And the last resort is to use new and delete, right?

user1914692
  • 3,033
  • 5
  • 36
  • 61
  • Please add code example to explain why you must destroy object _before the time of its end of scope_. You can always add extra `{}` to define smaller scopes. – timrau Dec 05 '14 at 17:03
  • 1
    [You can manually call the destructor of the original object, and then use placement `new` to create a new object on top of that memory](http://stackoverflow.com/questions/2494471/c-is-it-possible-to-call-a-constructor-directly-without-new). If you do this, document things clearly, as it might seriously confuse/mislead readers of the code. – Cornstalks Dec 05 '14 at 17:04
  • Can you implement the two halves as separate functions? Or separate blocks within a function? That would be much simpler than manual control (although that is possible, to some extent, if you really need it). – Mike Seymour Dec 05 '14 at 17:09
  • Before you start to play with placement new, check how the memory is handled by your classes. Do they allocate memory internally (e.g. using new in constructors)? Do they occupy big areas themselves, or their members do? – Wojtek Surowka Dec 05 '14 at 17:10
  • @timrau, Mike Seymour, The above half part and the below half part use many common variables. So it seems scope {} method makes it inconvenient, since I don't want to create a function with too many parameters. – user1914692 Dec 05 '14 at 17:18
  • @Cornstalks, do I have to use placement new? As you said, it is too complicated. I hope the compiler will manage that part of memory. If I do not use placement new, and manually call the destructor, can the compiler make use of that part old memory? – user1914692 Dec 05 '14 at 17:19
  • @WojtekSurowka, yes, the class internally allocate a large chunk of memory. – user1914692 Dec 05 '14 at 17:20
  • You don't need to declare all variables in the beginning of function in C++. Just reorder `a`, `b`, `c` and `d` later near their assignments. – timrau Dec 05 '14 at 17:21
  • @user1914692: You shouldn't manually call the destructor if you aren't' using placement new. Why not just use local scoping like Mike Seymour and others suggest (and keep the shared variables outside of the local scope, and `a`, `b`, `c`, and `d` inside the local scopes)? Though there's no guarantee here that the memory will get reused if you use scoping. I think placement new is the only way to guarantee the memory is reused. – Cornstalks Dec 05 '14 at 17:28
  • @Cornstalks, as you said "You shouldn't manually call the destructor if you aren't' using placement new". May I know why? Or give me some links to read? Thanks. – user1914692 Dec 05 '14 at 17:51
  • Because the compiler will automatically call the destructor when the object goes out of scope. If you manually call the destructor (and don't use placement new), then the destructor will get called twice (once by you, and once by the compiler when the object goes out of scope), which is undefined behavior. – Cornstalks Dec 05 '14 at 18:15
  • @Cornstalks, thanks. Destructors cannot be called twice, thanks. Placement new use pointers (cannot use classes directly), which is harder to handle. BTW, a question off the topic. Can constructors be called twice? That mean, can constructor be called on an already created object? I guess because when the constructor is called the second time, the first copy of the object is not properly deconstructed, so the answer is no? – user1914692 Dec 05 '14 at 18:20
  • No, a constructor can't be called twice either. – Cornstalks Dec 05 '14 at 19:12

4 Answers4

3

Use placement new and call the destructors manually:

{
  char memory[std::max(sizeof(A),sizeof(B))];

  A* pA = new (memory) A();
  // use `pA`
  pA->~A(); // destruct A

  B* pB = new (memory) B();
  // use `pB`
  pB->~B(); // destruct B
} // `memory` goes out of scope

I recommend to read this excellent resource on operator new: http://en.cppreference.com/w/cpp/language/new

erenon
  • 18,838
  • 2
  • 61
  • 93
2

You could break it down into smaller functions:

void part1() {
    monsterClass a, b;
    a = monsterClass(1000, 2000);
    b = monsterClass(2000, 3000);

    processMethod1(a, b);
}

or blocks within the larger function

{
    monsterClass a, b;
    // and so on
}
{
    dragonClass c, d;
    // and so on
}

or use temporaries

processMethod1(
    monsterClass(1000, 2000);
    monsterClass(2000, 3000);
);

If you're doing something so complicated that none of these are suitable, you could mess around with a union, or placement-new; the details would be fiddly, depending on exactly what your strange requirements are.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • The above half part and the below half part use many common variables. So it seems scope {} method makes it inconvenient, since I don't want to create a function with too many parameters. I prefer to use manually manage it. Is it possible? – user1914692 Dec 05 '14 at 17:21
  • @user1914692: I don't think that would make it particularly inconvenient. You'd have to declare the common variables outside the inner blocks; or maybe wrap them in a class, and pass that to the functions. As I said, manual management with a union or placement-new might be possible; but fiddly, and would depend on the details of your strange requirements. I'd try hard to use conventional scopes before resorting to that kind of weirdness. – Mike Seymour Dec 05 '14 at 17:25
  • you are right. Your answer is similar to timrau's. I could put common variables outside those blocks. – user1914692 Dec 05 '14 at 17:31
1

You can control the lifetime manually of objects on the stack by using braces.

void foo()
{
    int x = 5;
    int y = 2;

    {          // This introduces a new scope
    int z = 3;
    }          // After this brace, z is now out of scope

    int a = x + y;
}

But note that once the variable falls out of scope, when this memory is used again is not specified. Just because I declared another int named a, doesn't mean it will be assigned the address where z used to be.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • I don't care whether a new variable exactly makes use of the memory of the old variable. But I hope the compiler is smart enough to make use of the memory of the abandoned variables. Is it the case for modern compilers? – user1914692 Dec 05 '14 at 17:22
  • Yes, once the variable falls out of scope, using the method I showed or the solutions by Mike or erenon, that memory is free for use for some other object. I just wanted to make sure you were aware that that specific location won't necessarily be immediately reused. – Cory Kramer Dec 05 '14 at 17:24
1

As your code snippet, you could write as

int i,j,k,l;

{
  monsterClass a(1000, 2000);
  monsterClass b(2000, 3000);
  i = processMethod1(a, b);
  j = ...;
  k = ...;
  l = ...;
}

// here, you want to destroy a, b, since they are not used any more, while occupy memory.

dragonClass c(400, 3000);
dragonClass d(500, 4000);
processMethod2(c, d, i);
j = ...;
k = ...;
l = ...;

// you could use the same technique if there are still e, f or so
timrau
  • 22,578
  • 4
  • 51
  • 64
  • thanks. I come up another situation. In this situation, the scopes of different variables are interwined! It is like this: the scope of a has an overlap of scope of b, but they are not including relationship. It is overlap partly relationship. In this case, the last resort is to use new and delete, right? – user1914692 Dec 05 '14 at 20:42