I want to reset an object. Can I do it in the following way?
anObject->~AnObject();
anObject = new(anObject) AnObject();
// edit: this is not allowed: anObject->AnObject();
This code is obviously a subset of typical life cycle of an object allocated by in placement new:
AnObject* anObject = malloc(sizeof(AnObject));
anObject = new (anObject) AnObject(); // My step 2.
// ...
anObject->~AnObject(); // My step 1.
free(anObject)
// EDIT: The fact I used malloc instead of new doesn't carry any meaning
The only thing that's changed is the order of constructor and destructor calls.
So, why in the following FAQ
all the threatening appear?
[11.9] But can I explicitly call a
destructor if I've allocated my object
with new?
FAQ: You can't, unless the object was
allocated with placement new. Objects
created by new must be deleted, which
does two things (remember them): calls
the destructor, then frees the memory.
FQA: Translation: delete is a way to
explictly call a destructor, but it
also deallocates the memory. You can
also call a destructor without
deallocating the memory. It's ugly and
useless in most cases, but you can do
that.
The destructor/constructor call is obviously normal C++ code. Guarantees used in the code directly result from the in placement new guarantees. It is the core of the standard, it's rock solid thing. How can it be called "dirty" and be presented as something unreliable?
Do you think it's possible, that the in-placement and non-in-placement implementation of new are different? I'm thinking about some sick possibility, that the regular new can for example put size of the memory block allocated before the block, which in-placement new obviously would not do (because it doesn't allocate any memory). This could result in a gap for some problems... Is such new() implementation possible?
Don't get sucked in by the FQA troll. As usual he gets the facts wrong.
You can certainly call the destructor directly, for all objects whether they are created with placement new or not. Ugly is in the eye of the beholder, it is indeed rarely needed, but the only hard fact is that both memory allocation and object creation must be balanced.
"Regular" new/delete simplifies this a bit by tying memory allocation and object creation together, and stack allocation simplifies it even further by doing both for you.
However, the following is perfectly legal:
int foo() {
CBar bar;
(&bar)->~CBar();
new (&bar) CBar(42);
}
Both objects are destroyed, and the stack memory is automatically recycled too. yet unlike the FQA claims, the first call of the destructor is not preceded by placement new.
Why not implement a Clear() method, that does whatever the code in the body of the destructor does? The destructor then just calls Clear() and you call Clear() directly on an object to "reset it".
Another option, assuming your class supports assignment correctly:
MyClass a;
...
a = MyClass();
I use this pattern for resetting std::stack instances, as the stack adaptor does
not provide a clear function.
Technically it is bad practice to call constructors or destructors explicitly.
The delete keyword ends up calling them when you use it. Same goes for new with constructors.
I'm sorry but that code makes me want to tear my hair out. You should be doing it like this:
Allocate a new instance of an object
AnObject* anObject = new AnObject();
Delete an instance of an object
delete anObject;
NEVER do this:
anObject->~AnObject(); // My step 1.
free(anObject)
If you must "reset" an object, either create a method which clears all the instance variables inside, or what I would recommend you do is Delete the object and allocate yourself a new one.
"It is the core of the language?"
That means nothing. Perl has about six ways to write a for loop. Just because you CAN do things in a language because they are supported does mean you should use them. Heck I could write all my code using for switch statements because the "Core" of the language supports them. Doesn't make it a good idea.
Why are you using malloc when you clearly don't have to. Malloc is a C method.
New and Delete are your friends in C++
"Resetting" an Object
myObject.Reset();
There you go. This way saves you from needlessly allocating and deallocating memory in a dangerous fashion. Write your Reset() method to clear the value of all objects inside your class.
You cannot call the constructor in the manner indicated by you. Instead, you can do so using placement-new (like your code also indicates):
new (anObject) AnObject();
This code is guaranteed to be well-defined if the memory location is still available – as it should be in your case.
(I've deleted the part about whether this is debatable code or not – it's well-defined. Full stop.)
By the way, Brock is right: how the implementation of delete isn't fixed – it is not the same as calling the destructor, followed by free. Always pair calls of new and delete, never mix one with the other: that's undefined.
Yes, what you are doing is valid most of the time. [basic.life]p8 says:
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
the storage for the new object exactly overlays the storage location which the original object occupied, and
the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
neither the original object nor the new object is a potentially-overlapping subobject ([intro.object]).
So it is legal if you don't have a const or reference member.
If you don't have this guarantee, you need to use std::launder or use the pointer returned by placement new (like you're doing anyways) if you want to use the new object:
// no const/ref members
anObject->~AnObject(); // destroy object
new (anObject) AnObject(); // create new object in same storage, ok
anObject->f(); // ok
// const/ref members
anObject->~AnObject();
auto newObject = new (anObject) AnObject();
anObject->f(); // UB
newObject->f(); // ok
std::launder(anObject)->f(); // ok
Note that they're not malloc and free that are used, but operator new and operator delete. Also, unlike your code, by using new you're guaranteeing exception safety. The nearly equivalent code would be the following.
AnObject* anObject = ::operator new(sizeof(AnObject));
try
{
anObject = new (anObject) AnObject();
}
catch (...)
{
::operator delete(anObject);
throw;
}
anObject->~AnObject();
::operator delete(anObject)
The reset you're proposing is valid, but not idiomatic. It's difficult to get right and as such is generally frowned upon and discouraged.
Why not reset using the operator=()? This is not debatable and by far more readable.
A a;
//do something that changes the state of a
a = A(); // reset the thing
You can't call the constructor like that, but there's nothing wrong with reusing the memory and calling placement new, as long you don't delete or free (deallocate) the memory. I must say reseting an object like this is a little sketchy. I would write an object to be explicitly resetable, or write a swap method and use that to reset it.
E.g.
anObject.swap( AnObject() ); // swap with "clean" object
If your object has sensible assignment semantics (and correct operator=), then *anObject = AnObject() makes more sense, and is easier to understand.
It is far better just to add something like a Reset() method to your object rather than play with placement new's.
You are exploiting the placement new feature which is intended to allow you to control where an object is allocated. This is typically only an issue if your hardware has "special" memory like a flash chip. IF you want to put some objects in the flash chip, you can use this technique. The reason that it allows you to explicitly call the destructor is that YOU are now in control of the memory, so the C++ compiler doesn't know how to do the deallocation part of the delete.
It is not saving you much code either, with a reset method, you will have to set the members to their starting values. malloc() doesn't do that so you are going to have to write that code in the constructor anyway. Just make a function that sets your members to the starting values, call it Reset() call it from the constructor and also from anywhere else you need.
Related
I was trying to solve a problem that I ran into while programming the ESP8266 MCU, I basically needed to declare an object as global so that it wouldn't cause issues with the callbacks that one of the libraries does when the user sends an HTTP request, but I also needed to wait until I had some data from the EEPROM before calling the constructor so a lot of people told me that I should use placement new which worked perfectly for what I was trying to do. There's still something I don't understand though: after I have called the constructor for the object since it was declared globally and I'm trying to keep it around I shouldn't delete it by calling the destructor, but should I delete the first pointer that I used to save the object (I'm not entirely sure if I'm wording this right)?
class display{
public:
display(int b){
std::cout<<"the value of a: "<<b;
}
};
char *memory= new char[sizeof(display)];
display *obj;
int main(){
int a=69;
obj=new(memory) display(a);
return 0;
}
That is more or less what I did in the code for the ESP (without all the other stuff, but it is the same in terms of what I tried to do with placement new). My question is after someone does something like that, would it cause issues if I were to delete *memory or is it not necessary?
There is no need for the allocating new here. You just need to make sure that you have an array of sufficient size and alignment:
alignas(display) std::byte memory[sizeof(display)];
display *obj = nullptr;
(Instead of std::byte you can use unsigned char, but I think std::byte, which is available since C++17, expresses the intent as raw memory storage better.)
Then construct the object with
obj = new(memory) display(a);
and when it is not needed anymore, call its destructor explicitly:
obj->~display();
No delete is needed in this case. With your approach an additional delete[] memory; after the destructor call would be required to free the memory allocated with the first new, if you don't intent to reuse it after the destructor call (which you can do e.g. in a loop constructing a new display with placement-new). Note that you need to call the destructor on obj and the delete[] on memory. This is not interchangeable. memory is a pointer to the allocated memory block and obj a pointer to the object nested in it. The former was allocated with allocating new[], so required delete[], and the latter was only created with the (non-allocating) placement-new, so requires only an explicit destructor call.
Of course, you can consider whether the destructor call is really needed. If the display doesn't hold any resources that need to be cleaned up, then you can skip it, although I would be safe and call it anyway, just in case display will be changed later.
Also, the standard library since C++17 implements all of this as std::optional. If you can use it, then do so:
std::optional<display> obj;
// obj is now empty, can be tested with `if(obj)`
obj.emplace(/* constructor arguments */);
// obj now contains a display that can be accessed like a pointer with * and ->
// destructor of obj will take care of correctly destroying the display
emplace can also be called multiple times to replace the display with a new one (and calling the old one's destructor) or .reset() can be used to explicitly empty the optional.
If you don't have C++17 available, a std::unique_ptr can be used in a similar way, except that it will use a heap allcoation, which std::optional doesn't, and that std::unique_ptr isn't copyable even if display is, while std::optional will be.
std::optional<display> obj;
// obj is now empty, can be tested with `if(obj)`
obj = std::make_unique<display>(/* constructor arguments */);
// obj now contains a display that can be accessed like a pointer with * and ->
// destructor of obj will take care of correctly destroying the display
obj can be reassigned in that way multiple times as well or reset with = nullptr; or .reset() and in either case it will take care of correctly destroying any display just like std::optional does.
I want to reset an object. Can I do it in the following way?
anObject->~AnObject();
anObject = new(anObject) AnObject();
// edit: this is not allowed: anObject->AnObject();
This code is obviously a subset of typical life cycle of an object allocated by in placement new:
AnObject* anObject = malloc(sizeof(AnObject));
anObject = new (anObject) AnObject(); // My step 2.
// ...
anObject->~AnObject(); // My step 1.
free(anObject)
// EDIT: The fact I used malloc instead of new doesn't carry any meaning
The only thing that's changed is the order of constructor and destructor calls.
So, why in the following FAQ
all the threatening appear?
[11.9] But can I explicitly call a
destructor if I've allocated my object
with new?
FAQ: You can't, unless the object was
allocated with placement new. Objects
created by new must be deleted, which
does two things (remember them): calls
the destructor, then frees the memory.
FQA: Translation: delete is a way to
explictly call a destructor, but it
also deallocates the memory. You can
also call a destructor without
deallocating the memory. It's ugly and
useless in most cases, but you can do
that.
The destructor/constructor call is obviously normal C++ code. Guarantees used in the code directly result from the in placement new guarantees. It is the core of the standard, it's rock solid thing. How can it be called "dirty" and be presented as something unreliable?
Do you think it's possible, that the in-placement and non-in-placement implementation of new are different? I'm thinking about some sick possibility, that the regular new can for example put size of the memory block allocated before the block, which in-placement new obviously would not do (because it doesn't allocate any memory). This could result in a gap for some problems... Is such new() implementation possible?
Don't get sucked in by the FQA troll. As usual he gets the facts wrong.
You can certainly call the destructor directly, for all objects whether they are created with placement new or not. Ugly is in the eye of the beholder, it is indeed rarely needed, but the only hard fact is that both memory allocation and object creation must be balanced.
"Regular" new/delete simplifies this a bit by tying memory allocation and object creation together, and stack allocation simplifies it even further by doing both for you.
However, the following is perfectly legal:
int foo() {
CBar bar;
(&bar)->~CBar();
new (&bar) CBar(42);
}
Both objects are destroyed, and the stack memory is automatically recycled too. yet unlike the FQA claims, the first call of the destructor is not preceded by placement new.
Why not implement a Clear() method, that does whatever the code in the body of the destructor does? The destructor then just calls Clear() and you call Clear() directly on an object to "reset it".
Another option, assuming your class supports assignment correctly:
MyClass a;
...
a = MyClass();
I use this pattern for resetting std::stack instances, as the stack adaptor does
not provide a clear function.
Technically it is bad practice to call constructors or destructors explicitly.
The delete keyword ends up calling them when you use it. Same goes for new with constructors.
I'm sorry but that code makes me want to tear my hair out. You should be doing it like this:
Allocate a new instance of an object
AnObject* anObject = new AnObject();
Delete an instance of an object
delete anObject;
NEVER do this:
anObject->~AnObject(); // My step 1.
free(anObject)
If you must "reset" an object, either create a method which clears all the instance variables inside, or what I would recommend you do is Delete the object and allocate yourself a new one.
"It is the core of the language?"
That means nothing. Perl has about six ways to write a for loop. Just because you CAN do things in a language because they are supported does mean you should use them. Heck I could write all my code using for switch statements because the "Core" of the language supports them. Doesn't make it a good idea.
Why are you using malloc when you clearly don't have to. Malloc is a C method.
New and Delete are your friends in C++
"Resetting" an Object
myObject.Reset();
There you go. This way saves you from needlessly allocating and deallocating memory in a dangerous fashion. Write your Reset() method to clear the value of all objects inside your class.
You cannot call the constructor in the manner indicated by you. Instead, you can do so using placement-new (like your code also indicates):
new (anObject) AnObject();
This code is guaranteed to be well-defined if the memory location is still available – as it should be in your case.
(I've deleted the part about whether this is debatable code or not – it's well-defined. Full stop.)
By the way, Brock is right: how the implementation of delete isn't fixed – it is not the same as calling the destructor, followed by free. Always pair calls of new and delete, never mix one with the other: that's undefined.
Yes, what you are doing is valid most of the time. [basic.life]p8 says:
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
the storage for the new object exactly overlays the storage location which the original object occupied, and
the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
neither the original object nor the new object is a potentially-overlapping subobject ([intro.object]).
So it is legal if you don't have a const or reference member.
If you don't have this guarantee, you need to use std::launder or use the pointer returned by placement new (like you're doing anyways) if you want to use the new object:
// no const/ref members
anObject->~AnObject(); // destroy object
new (anObject) AnObject(); // create new object in same storage, ok
anObject->f(); // ok
// const/ref members
anObject->~AnObject();
auto newObject = new (anObject) AnObject();
anObject->f(); // UB
newObject->f(); // ok
std::launder(anObject)->f(); // ok
Note that they're not malloc and free that are used, but operator new and operator delete. Also, unlike your code, by using new you're guaranteeing exception safety. The nearly equivalent code would be the following.
AnObject* anObject = ::operator new(sizeof(AnObject));
try
{
anObject = new (anObject) AnObject();
}
catch (...)
{
::operator delete(anObject);
throw;
}
anObject->~AnObject();
::operator delete(anObject)
The reset you're proposing is valid, but not idiomatic. It's difficult to get right and as such is generally frowned upon and discouraged.
Why not reset using the operator=()? This is not debatable and by far more readable.
A a;
//do something that changes the state of a
a = A(); // reset the thing
You can't call the constructor like that, but there's nothing wrong with reusing the memory and calling placement new, as long you don't delete or free (deallocate) the memory. I must say reseting an object like this is a little sketchy. I would write an object to be explicitly resetable, or write a swap method and use that to reset it.
E.g.
anObject.swap( AnObject() ); // swap with "clean" object
If your object has sensible assignment semantics (and correct operator=), then *anObject = AnObject() makes more sense, and is easier to understand.
It is far better just to add something like a Reset() method to your object rather than play with placement new's.
You are exploiting the placement new feature which is intended to allow you to control where an object is allocated. This is typically only an issue if your hardware has "special" memory like a flash chip. IF you want to put some objects in the flash chip, you can use this technique. The reason that it allows you to explicitly call the destructor is that YOU are now in control of the memory, so the C++ compiler doesn't know how to do the deallocation part of the delete.
It is not saving you much code either, with a reset method, you will have to set the members to their starting values. malloc() doesn't do that so you are going to have to write that code in the constructor anyway. Just make a function that sets your members to the starting values, call it Reset() call it from the constructor and also from anywhere else you need.
which is better for memory allocation in c++ for classes and template. malloc() or new; can malloc() be used to allocate memory for classes or template?
It is possible to do this, although not the way you do it, and in any case it's not really beginner stuff. The reason your approach does not work is that an uninitialized slab of memory is not the same as a valid object. But before I continue:
IMPORTANT STYLE NOTE: I am going to leave aside for the sake of brevity the usual memory management mechanics (smart pointers et al) that you should stick to religiously as a beginner (and, in fact, as an expert, but they don't need to be told). Do not use code like what I'm about to show here in production (not without all the necessary bookkeeping around it), or things will break in ways that are horrible to debug. I'm only doing it because doing it properly would obscure the mechanics I'll try to show.
The difference between a slab of uninitialized memory and a valid object are, in a broad sense, class invariants. What this means is that a class defines certain properties for its objects that these always fulfill. For example, a string class will generally guarantee that the pointer to its data will not be a dangling pointer, and that its size will not reported to be larger than the block of memory that pointer points to. An uninitialized slab of memory cannot guarantee either of those things, and that is why we have constructors. A constructor is a function that constructs an object into an uninitialized slab of memory, fixing these invariants, and most of the time it is called for you automatically. If you write
Foo f;
memory is obtained from the stack (simplified terminology; please bear with me, language lawyers), and the default constructor Foo::Foo() is called on that piece of memory. Similarly, if you write
Foo *p = new Foo();
operator new obtains memory from the heap and calls the constructor on that piece of memory. Possibly it does more than that, but let's leave that possibility aside for now.
So what goes wrong in your code? Well, when you write
*obj = A();
this is an assignment. It assumes that there is a valid object *obj that a newly constructed object can be copied into. This is not the case, because obj points to an uninitialized slab of memory.
So, before you can use your uninitialized slab of memory like an object, you have to construct one into it. This is possible, and it is called placement new. The syntax looks like this:
new(obj) A();
And later you have to call the destructor (the constructor's counterpart; its purpose is to undo what the constructor did) manually like so:
obj->~A();
...after which obj will again point to uninitialized memory, and (unless the class is buggy) all necessary cleanup has been done. Except giving back the slab of memory, because that was allocated outside the constructor/destructor duo. Normally it would happen automatically at the end of the scope (for automatic variables like f above) or delete would do it for you (for dynamic storage objects like *p above), but since you did the allocation yourself, you have to do the deallocation yourself.
The use of malloc() for allocatiog C++ objects shall be avoided.
Rewrite your main() using C++ practice:
A *obj = new A(); // get memory and initialize the object
B<int> *objb = new B<int>(); // same
This works better and is easier to read !
Remark: Statements like *obj=A(); may call a class specific assignment operator, which would assume that *obj was already initialized by a constructor and is in a valid state. If memory was simply aquired by malloc(), this assumption is not fulfilled.
If I create an object without using the new keyword such as 'Object s(someval)', but that objects constructor uses new, when that object goes out of scope, will the destructor be called for it's new allocation? I feel as though it is, but I'm unsure.
Let’s give names to the objects, shall we?
struct A {
A() b(new B) {}
B* b;
C c;
};
A a;
Here, a’s destructor is called. So is A::c’s destructor (which is called automatically when a is destructed).
However, *A::b’s destructor is not called – actually, the pointer object A::b itself is properly released but since it’s a primitive type (it’s a pointer!) nothing happens. The pointee *A::b however needs to be manually destructed (and its memory released) by calling delete.
when that object goes out of scope, will the destructor be called for it's new allocation?
It depends on how Object is defined.
If the pointer returned by new is stored in some data member of Object on which delete gets called by the destructor of Object itself, then yes, the object allocated with new will be destroyed as well when s goes out of scope.
Otherwise, no. Every call to new must be matched by a corresponding call to delete before you lose the last pointer/reference to the allocated object, otherwise you will have a memory leak.
Since it is easy to fail to do so, and since it is also easy to dereference by mistake a pointer which is dangling (i.e. pointing to an object whose lifetime has ended), it is usually preferable to avoid performing manual memory management through raw pointers, new and delete (or their array counterparts).
When you need to control an object's lifetime, always prefer using RAII wrappers such as std::shared_ptr<> or std::unique_ptr<> unless you really know what you are doing and can't do otherwise.
No, you have to explicitly delete it in the destructor if you store that dynamically-allocated pointer as a data member. This also introduces the Rule of Three (Rule of Five in C++11), which is a bother. This is why stack-allocated objects should be preferred when possible.
When a pointer is necessary, make use of an RAII wrapper, such as std::vector for a dynamically-allocated array or a smart pointer, such as std::unique_ptr or std::shared_ptr, for a single dynamically-allocated object. These manage the memory for you and to you, it's no extra work.
No, it won't...
You have to define the delete in your destructor of the object you allocated using new.
You create an object on the heap using new and when your object is destroyed you will lose the reference to the object creating a memory-leak.
To avoid this, you might use a smart-pointer like shared_ptr.
No you will have to call delete explicitly for that object in the destructor
I have an object with some pointers inside of it. The destructor calls delete on these pointers. But sometimes I want to delete them, and sometimes I don't. So I'd like to be able to delete the object without calling the destructor. Is this possible?
Edit: I realize this is an AWFUL idea that no one should ever do. Nonetheless, I want to do it because it will make some internal functions much easier to write.
The delete operator does two things to the object you pass it:
calls the appropriate destructor.
calls the deallocation function, operator delete.
So deleting an object without calling a destructor means you want to simply call operator delete on the object:
Foo *f = new Foo;
operator delete(f);
operator delete is a normal function call and the usual name lookup and overload resolution is done. However the delete operator has its own rules for finding the correct operator delete. For example the delete operator will look for member operator delete functions that the usual name lookup and overload resolution does not find. That means that you need to make sure you're calling the right function when you manually use operator delete.
As you say, using operator delete directly is an awful idea. Failing to call the destructor breaks RAII, resulting in resource leaks. It can even lead to undefined behavior. Also, you'll have to take on the responsibility of writing exception safe code without RAII, which is exceptionally hard. You're almost guaranteed to get it wrong.
You can set the pointers to NULL, then the destructor will not delete them.
struct WithPointers
{
int* ptr1;
int* ptr2;
WithPointers(): ptr1(NULL), ptr2(NULL) {}
~WithPointers()
{
delete ptr1;
delete ptr2;
}
}
...
WithPointers* object1 = new WithPointers;
WithPointers* object2 = new WithPointers;
object1->ptr1 = new int(11);
object1->ptr2 = new int(12);
object2->ptr1 = new int(999);
object2->ptr2 = new int(22);
...
int* pointer_to_999 = object2->ptr1;
object2->ptr1 = NULL;
delete object1;
delete object2; // the number 999 is not deleted now!
// Work with the number 999
delete pointer_to_999; // please remember to delete it at the end!
Eww! Yes, it's possible, no I wouldn't do it. Have the objects that need variable lifetime be controlled via a shared pointer or some other reference counted object instead. Cleaner to work with C++ than breaking some of its internal tenants...
Whatever you're actually trying to do, there is a problem with your code.
If you don't want to delete the sub-objects, just use a boolean flag that you will set before deleting the object and that will be taken into account by the destructor.
But honestly, you should be using smart pointers instead of naked pointers (and in your very case, it looks like shared pointers are what you need).
Write a method that you can call before calling the destructor. The method will flip a member boolean. When the destuctor is called, it will check that boolean member and destroy the pointer if it is true, and keep it if it is false.
I wouldn't recommend doing this. Better for the class to not take responsibility for deleting the pointer.
Yes, this is possible. std::vector does this, in that it allocates buffers with space for objects, then conditionally constructs them (in-place) and destroys them, managing the memory independently of the object lifetime.
In C++11, I'd use a union of your type and a small type with trivial constructors/destructors to indicate a memory location that can fit your type, but doesn't have to have that type in it. External to that you have to track if the object is actually there. Creating the item consists of using placement new, and destroying it consists of manually calling the destructor.
The buffer of the union objects, be it N objects or 1, would be managed completely independently. The default constructor of the union would either construct nothing, or construct the trivial type (in which case you might want to destroy that trivial type).
However, odds are that the real answer to your question is "don't do that". And if you do that, you wrap the pointers in a class whose only job is handling the above mess. Classes of that type (whose job is to manage a pointer's lifetime and pointer-like properties) are called "smart pointers".
As others have suggested, the correct way to solve this problem isn't to NOT call the destructor [you only need to add something like std::string or std::vector to your object, and all of a sudden you have a memory leak]. The correct way is to either not let your object own those other objects at all (e.g. delete them separately before/after the object is deleted), or have a method with which the object knows whether to delete the pointers or not.