I should delete new instances in C++, right?
class C {
public:
void hello() {...};
};
If I have an instance of the class above, I may have to use it like
C* c = new C();
c->hello();
delete c;
right? How about this:
(new C())->hell();
Can I do this? Is destructor automatically called and free the memory?
No, destructor is not called automatically because you never call delete. However you can create a smart pointer that will do it for you at one go:
::std::make_unique<C>()->helo();
In modern c++ there is no reason to new-up resources anymore. Instead you can use the memory library as following:
#include <memory>
#include <iostream>
class C
{
public:
C(int a) : _a(a) { }
void printA() { std::cout << _a << std::endl; }
private:
int _a;
};
std::make_unique<C>(3)->printA(); // prints 3
// or via variable
auto c = std::make_unique<C>(123);
c->printA(); // prints 123
In here, the resources are already taken care off and you can't forget deleting something you allocated somewhere else.
No in the second case the destructor will not be called and also you will have memory leak. The destructor of a dynamically allocated objects is called only when explicitly calling delete.
Related
I have just started using std::variant in my projects. I have a doubt. What will the destructor of std::variant do in the code shown below. Variant holds a void* data. Once variant goes out of scope, I think it will only free the memory of void* but not the actual object the pointer was pointing to. So there will be memory leak in this case. I would like to know if my understanding is correct or not.
#include <iostream>
#include <memory>
#include <variant>
using namespace std;
class A {
public:
~A(){
cout<<"Destructor called"<<endl;
}
};
int main() {
std::variant<void*> data;
A* b = new A();
data = (void*)b;
return 0;
}
When the variant destructor fires, it will call the destructor for whatever type of item is stored in the variant at that point. If that’s a void*, then C++ will say “okay, I will clean up the void*, and since that’s a primitive type, that’s a no-op.” It won’t look at the void*, realize that it’s actually a pointer to an A, and then delete the pointer as though it’s an A*.
The comments have pointed out that it’s fairly unusual to use a variant of a void*. A void* means “I’m pointing at something, and it’s up to you as the user to keep track of what it is and do the appropriate casting and resource management.” A variant means “I’m holding one of the following actual things, and I want C++ to remember which one and to do the appropriate resource management for me.” You may want to rethink your design, as there might be an easier way to do whatever you’re aiming to do here.
You are correct. The only pointer owning classes in the standard library that actually does delete (or delete[]) on pointers are the smart pointers.
std::variant is supposed to support you to hold one object of any number of types and primarily not pointers to objects. If the variant contains pointers, it means that some other object owns the data and is responsible for deleting it.
A std::variant capable of holding only one type is rarely useful either. You can declare the variable as a normal variable of that type in that case.
Here's one example of using a std::variant capable of holding objects of two unrelated types, and destruction will happen as expected.
#include <iostream>
#include <variant>
class A {
public:
~A() { std::cout << "A destructor called\n"; }
};
class B {
public:
B() {}
B(const B&) = default;
B& operator=(const B&) = default;
~B() { std::cout << "B destructor called\n"; }
};
int main() {
std::variant<A, B> data; // now holds a default constructed A
data = B(); // deletes the A and now holds a default constructed B
std::cout << "---\n";
}
Output:
A destructor called // in "data = B()", the A must be destroyed
B destructor called // the temporary B used in "data = B()"
---
B destructor called // the B in the variant when the variant goes out of scope
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Quick question,
I'm new to C++ and I'm having difficulty understanding the destructors.
I'll explain; lets say we have the following;
int _a;
a::a(int x) {
_a = x
}
then we have
a* a1 = new a(8);
I understand that a1's data is created on the heap, and a1 is a pointer, where I'm failing is with the destructor;
a::~a() {
// confusion here
}
Since _a is not a pointer since it was created implicitly on the heap thanks to new (correct) we cannot delete it so what do we do?
Does
delete a1;
call the destructor for a int automatically?
call the destructor for a int automatically?
That would be true if the object were a class type. For non-class types, there is no destrutor, not even implicitly defined ones. Hence, the question of calling the destructor does not arise.
Had your code been something like:
struct Foo
{
Foo() {}
~Foo() {}
};
struct a
{
Foo f
};
a* aptr = new a;
delete aptr;
The destructor, Foo::~Foo(), will be called for f.
I understand what you're driving at and the answer is no, C++ destructors do not automatically destroy the data that your class contains. Unfortunately your example is too contrived to highlight the problem well. int is a primitive type so its destruction is primitive (someone might want to comment on what actually happens in ints destructor). Take the following example:
class A
{
public:
int x;
~A()
{
std::out << "in A destructor" << std::endl;
}
};
class B
{
public:
A* x;
B()
{
x = new A();
}
~B()
{
std::out << "in B destructor" << std::endl;
// does not automatically delete x
}
};
auto x = new B();
delete x;
In this example, constructing an instance of B will also construct an instance of A because you explicitly new it up in the constructor of B. However, unless you explicitly delete x in your destructor for B it will not automatically be deleted.
A slight variation of me previous example would be if B::x were of type A and not A*, in which case the answer is yes, the destructor for A would be called.
I hope this helps!
The destructor is just a function that is called automatically when the instance comes out of scope. It's a convenient way to release dynamically allocated memory.
You don't have to worry about releasing variables that were allocated on the stack (anything that is declared and not new-ed).
For example:
int localStackVar = 5; //no need to deallocate explicitly
int* localPointer = &localStackVar // no need to deallocate explicitly
int* heapValue = new int(); //Allocates to the heap so you need to call delete explicitly
The first two from the example above are on the stack, the first one is an int and the second is an int pointer, which is just a way to say it's a variable that holds the memory address of another variable.
Both of those will be deallocated automatically, since you did not call new on them.
The third line allocates an int on the heap. You have to call delete on it when you don't need it anymore.
If those 3 variables were a part of a class, your constructor and destructors would look like this:
MyClass::MyClass()
{
heapValue = new int();
}
MyClass::~MyClass() //destructor
{
delete heapValue;
}
void someFun()
{
MyClass instance; //constructor is called here
//do stuff
return; //destructor is called here
}
So while MyClass instance is a local stack variable when declared in someFun
since the constructor is called automatically, heapVal is made to point to a memory location that is on the heap which needs to be released explicitly.
If your destructor did not call delete on it, the memory would "leak" it will not be released until your program terminates.
Suppose a class and its usage
#include <vector>
class B
{
public:
B() {temp = 0;}; // implemented
~B() {} ; // implmented
private :
int temp;
// it holds a std::bitset , a std::vector.. It is quite large in size.
};
class A
{
private:
std::vector<B*> * _data ;
public:
A()
{
_data = new std::vector<B*>(0);
}
~A()
{
for(unsigned int idx_ = 0; idx_ < _data->size(); ++idx_)
delete _data->at(idx_);
delete _data ;
}
void addB()
{
B * temp = new B();
_data->push_back(temp);
}
}
int main()
{
A temp;
temp.addB();
// Do something
}
My question is does this code leak memory ? Also suppose another usage
int main()
{
A * temp = new A();
temp->addB();
delete temp ; // 1
}
Is 1 here required ? If I have a pointer to the heap and the pointer goes out of scope is the destructor called on the element in heap. I just want to be sure about this point.
Thank you !
To make it easier to associate when a destructor will be called and when it wont be, use this rule of thumb: When the memory for an object is being reclaimed, then the object's destructor is called (and the memory is reclaimed right after that).
Your first example does not leak any memory.
Here is why... You essentially created 2 objects.
A and B.
A was on the stack. The memory for object A was created implicitly on the stack.
B was created on the heap explicitly by your code.
When main() returned every Object on the stack is destroyed. i.e the memory that was being used to hold the members of the object on the stack (in this case object A) is being reclaimed implicitly. Since the object (A) is actually being destroyed and its memory being reclaimed, the destructor for A gets called.
Within A's destructor you are explicitly telling the runtime to reclaim all the memory what was explicitly allocated by your code (i.e when you call delete). Thus the memory for object B is being reclaimed too.
Thus there was no leak.
In the 2nd example, you again create 2 objects A and B.
Here, the memory for both objects resides in the heap. This was allocated explicitly by your code using the new operator.
In this case, your code never reclaims the memory allocated for A. i.e delete is never called for A.
The stack for main() only contains the memory for a pointer to A. The main() stack itself does not contain the memory for A. So when main() returns, all that is being destroyed is the memory that was allocated for the pointer to A, and not A itself.
Since the memory for A was never reclaimed, it was never "destroyed". Thus its destructor was never called and correspondingly "B" was never destroyed either.
No, destructor is not implicitly called. you have to delete temp, at which time it's destructor is called. It could be argued that since it's main that's returning in your example, the process is going to exit and memory will be reclaimed by OS, but in general, each new needs a delete.
The rule of thumb is if you've used new to create something then you have to use delete to destroy it. Pointers are all about manual memory management (they are heritage from the C language) or, as Scott Meyers once called them, "running with scissors". References are a C++ thing (or you can also check out smart pointers like std::shared_ptr).
UPDATE
I thought it would be useful to show an example with std::shared_ptr. It has dumb pointer semantics, but its destructor -since it actually has one- calls pointed object's destructor.
#include <memory>
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
struct Simple {
std::string txt;
Simple(const std::string& str) : txt(str) {}
Simple(){}
~Simple() { cout << "Destroyed " << txt << endl; }
};
template<class U> using SPtr = shared_ptr<U>;
template<class V> using PtrToSimple = typename conditional<is_same<SPtr<Simple>, V>::value,SPtr<Simple>,Simple*>::type;
template<class T>
void modify(PtrToSimple<T> pt) {
pt->txt.append("_modified");
// equivalent to (*pt).txt.append("_modified");
}
int main() {
auto shared = shared_ptr<Simple>(new Simple("shared_ptr_obj"));
modify<decltype(shared)>(shared);
cout << shared->txt << endl;
auto dumb = new Simple("dumb_ptr_obj");
modify<decltype(dumb)>(dumb);
cout << dumb->txt << endl;
// The object pointed by 'shared'
// will be automatically deleted.
// dumb's object won't
return 0;
}
prints
shared_ptr_obj_modified
dumb_ptr_obj_modified
Destroyed shared_ptr_obj_modified
#include <iostream>
#include <fstream>
#include <cstdio>
using namespace std;
class Derived
{
public:
Derived()
{
cout<< "Initialize...\n";
}
~Derived()
{
cout<< "Finalize...\n";
}
};
static Derived *obj=new Derived();
int main()
{
cout<<"Main Started::\n";
}
I'm trying to get the output as:
Initialize
MainStarted
Finalize
But getting:
Initialize
MainStarted
I tried to debug but its not getting into destructor. So I'm unable solve this problem.
You need to use
static Derived obj;
instead of
static Derived *obj=new Derived();
Now you create object with new, and never call delete, thus object will never be properly deleted.
Or you can use boost::scoped_ptr if you need heap allocated object for some reason.
static Derived *obj=new Derived();
That's a leak - the object has dynamic storage duration (since you've created it with new), and nothing deletes it, so it will never be destroyed.
If you want it to be destroyed automatically, then give the object static storage duration:
static Derived obj;
Alternatively, instead of defining a class with a destructor, you can use std::atexit to register an arbitrary function to call when the program exits:
#include <iostream>
#include <cstdlib> // for atexit
void goodbye() {std::cout << "Goodbye\n";}
int main() {
std::atexit(goodbye);
std::cout << "Hello\n";
}
Don't make the derived object a pointer. Since C++ is not java, there is little need for new in your case. But if you create the Derived on the heap, you'll have to make sure that it gets destroyed properly, by using RAII, i.e. a smart pointer. In your code you have a memory leak, the destructor of *obj gets never called.
Examples for how to do it right:
static Derived obj; //non-heap version
//C++03 auto_ptr, now deprecated:
static std::auto_ptr<Derived> obj(new Derived());
//C++11 smart pointers:
static std::unique_ptr<Derived> obj(new Derived());
static auto obj = std::make_shared<Derived>();
//Boost smart pointers, C++03 compatible:
static boost::shared_ptr<Derived> obj = boost::make_shared<Derived>();
static boost::scoped_ptr<Derived> obj(new Derived());
Pick one (the first, preferably).
Edit: But before you do any of these, you should give a really good reason for using that global variable.
you are using static Derived *obj=new Derived() but instead of use static Derived obj1 this will print as per your requirements.
// AirlineTicket.h
class AirlineTicket
{
public:
AirlineTicket();
~AirlineTicket();
int getNumberOfMiles();
private:
int mNumberOfMiles;
};
I want now what is the meaning of ~AirlineTicket(); in this code?
I don't know the meaning of ~ (tilde).
It is the destructor.
It gets called when you destroy (reaching end of scope, or calling delete to a pointer to) the instance of the object.
In the context you're using it, it defines a destructor.
In other context such as the following one, it's also called bitwise negation (complement):
int a = ~100;
int b = ~a;
Output: (ideone)
-101
100
~ signs that it is a destructor and when ever the object goes out of scope, corresponding destructor is called.
When the destructor is called ?
Taking an example -
#include <iostream>
class foo
{
public:
void checkDestructorCall() ;
~foo();
};
void foo::checkDestructorCall()
{
foo objOne; // objOne goes out of scope because of being a locally created object upon return of checkDestructorCall
}
foo:: ~foo()
{
std::cout << "Destructor called \t" << this << "\n";
}
int main()
{
foo obj; // obj goes of scope upon return of main
obj.checkDestructorCall();
return 0;
}
Results on my system:
Destructor called 0xbfec7942
Destructor called 0xbfec7943
This example just serves to indicate when a destructor is called. But destructor is written only when the class manages resources.
When class manages resources?
#include <iostream>
class foo
{
int *ptr;
public:
foo() ; // Constructor
~foo() ;
};
foo:: foo()
{
ptr = new int ; // ptr is managing resources.
// This assignment can be modified to take place in initializer lists too.
}
foo:: ~foo()
{
std::cout << "Destructor called \t" << this << "\n";
delete ptr ; // Returning back the resources acquired from the free store.
// If this isn't done, program gives memory leaks.
}
int main()
{
foo *obj = new foo;
// obj is pointing to resources acquired from free store. Or the object it is pointing to lies on heap. So, we need to explicitly call delete on the pointer object.
delete obj ; // Calls the ~foo
return 0;
}
Results on my system:
Destructor called 0x9b68008
And in the program, you posted I don't see a need to write destructor. Hope it helps !
It's the class destructor. You might want to pick up an introductory text on C++ development, as destructors are a fundamental concept in OOP. There is a good reference site here, and the C++ FAQ is another good resource.
~AirlineTicket(); is the destructor for the class AirlineTicket
see this link for further reference
The destructor is called when you delete the object of that class, to free any memory allocated or resources being used by the object.
~ introduces a destructor. It's used because (a) it was available, ad (b) ~ is one (of several) mathematical notation for "not".
This indicates destructor of class.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr380.htm