Deleting an Object in c++ implies deletion of its members? - c++

I am quite new to c++ and I have a question.
If I have a class containing a (pointer to a) vector:
class myClass {
public:
int* direction;
myClass(int d){direction=new int[d];}
}
When I create an object and delete it in the main:
int main(){
int d;
myClass* myvec;
myvec = new myClass(d);
delete myvec;
}
Also the destructor for myvec->direction has been coherently called and the memory freed? Or do I have to write an apposite method for that?
I hope the question is clear...

If you've allocated memory with new you need to delete it too, like this:
class myClass {
int* direction;
public:
myClass(int d) : direction(new int[d]) {}
~myClass() {
delete[] direction;
}
}
But you'd also need to write a copy constructor and copy assignment operator, and in C++11 and later also a move constructor and move assignment operator, for this to be working good. Otherwise, you'd risk the default versions of those copying the raw pointer when you use instances of this class.
Take a look at the rule of three/five/zero.
You'd be much better off using a std::vector<int> instead of a raw pointer.

Related

Class constructors in C++

I'm a beginner to c++ so there are a lot of things quite not clear in my mind.
I have this code I need to write and in a class I make a constructor.
However, I don't need any parameters because I read from a file-stream inside the constructor. So my questions are:
1.Can I make a constructor like this:
class myClass {
private:
string title;
string organizer;
public:
myClass() {
title = stringRead();
organizer = stringRead();
}
}
where stringRead() is a function I have written to read from my file??
2.How do I call it afterwards when I need it? I know that the default constructror is being called like that:
myClass A;
A = myClass();
Is it the same?
3.If I have a pointer, how do I call the constructor again? This doesn't seem like it should be right...
myClass *B;
B = myClass();
Thanks in advance! =D
1) This constructor will work but you should favor using an initialization list (assuming stringRead() isn't a member function of myClass
class myClass {
private:
string title;
string organizer;
public:
myClass()
: title(stringRead()),
organizer(stringRead())
{ }
};
2) myClass A; is what you should be doing. You could alternatively have auto A = myClass(); which, after optimizations, will be the same thing. Without optimizations a temporary will be constructed, and then A will be move constructed from it, so this won't work with unmovable objects (your object is movable)
3) If you want to use a raw pointer then you would use
myClass *ptr = new myClass;
// bunch of code
delete ptr;
However, you'd be better using a smart pointer to control its lifetime. This way you won't need to manually delete
std::unique_ptr<myClass> ptr(new myClass);
or make_unique in c++14
auto ptr = std::make_unique<myClass>();
And of course use a shared_ptr if you have shared ownership
I think it's OK to assign the value returned by a function to a member of a class.
You can initialize it as you suggested (with myClass A;)
When you use pointers, you need myClass *k=new myClass();. You should remember to delete the object you created with delete k;.
Your constructor is fine, so long as the functions used within it are globals or static functions of this or another class.
myClass A; will invoke the constructor you have written.
To use a pointer, you need B = new myClass(). That will also call the same constructor. Don't forget to delete B at some point else you'll leak memory.
Do bear in mind that if an exception is thrown in a constructor then the destructor is not called.
Yes, you can, but it might not be the best approach. Reading from input can fail, failure in a constructor is often a non-recoverable event you'll want to handle. A good approach is reading the values outside the costructor, handling errors and calling the constructor only when you have "everything ready". Like this:
class myClass {
private:
string _title;
string _organizer;
public:
myClass(const string &title, const string &organizer) {
_title = title;
_organizer = organizer;
}
or, by using a more idiomatic C++ initializer list:
class myClass {
private:
string _title;
string _organizer;
public:
myClass(const string &title, const string &organizer):
_title(title), _organizer(organizer) {}
}
and then, somewhere else:
string title = stringRead();
string organizer = stringRead();
myClass A(title, organizer);
No, in this snippet:
myClass A;
A = myClass();
two different things happen: at line 1 the default constructor is called; at line 2, a temporary object is constructed (again, by calling the default constructor) and then assigned to A using the (rval for C++11) copy operator. This expression:
myClass A;
calls the default constructor. If you have parameters:
myClass A(title, organizer);
Nope, this does not even work. A pointer is not an object, you have to allocate the object. At that point, you can get a pointer to it:
myClass A;
myClass *B = &A;
you could also resort to dynamic allocation:
myClass *B = new myClass;
in this case, either remember to call delete B somewhere else or wrap B in a smart pointer:
std::unique_ptr<myClass> B(new myClass());

Using destructor in class

I've got a project in C++ that uses classes(quite basic elements).
My class looks like this:
class vehicule: public frane,public motor,public directie,public noxe,public caroserie
{
char tip[40];
int placfatacant,placfatatot;
static const int placfatapret=18;
int placspatecant,placspatetot;
static const int placspatepret=15;
public:
vehicule()
void settip(char)
void verifauto()
;};
I've been told I have to use copy constructor and destructor. I have some examples,but both use dynamic allocation. Now my question is:what should my copy constructor/destructor do as I don't have dynamic allocated memory to copy/delete? Or should I declare the data as
int *placfatacant
and then use
delete placfatacant
?
Thanks in advance!
You only need to declare a constructor if you need to handle the deletion of dynamically allocated variables, as you said. In general, for every new, there must be a delete.
I don't see any new'd objects in your class, so I would just let the compiler-generated destructor/copy constructor do its thing. Your class is entirely statically allocated and will be deleted when it falls out of scope of the context in which it is used.
If it is for school purpose you can change :
// From:
char tip[40];
// To:
char * tip;`
And then in your constructor you will make:
tip = new char[40]();
Now you have to create a copy constructor like this one:
vehicule(const vehicule & toCopy)
{
tip = new char[40]();
strcpy(tip, toCopy.tip);
}
Your destructor just need to deallocate tip:
~vehicule()
{
delete tip;
}

delete nested class objects correctly?

My code is like following, basically I am using some external library and embed some class objects from this library to myClass, then do things with OBJ,
#include "extern_lib.h" //some library
class myClass
{
public:
extern_class *obj1;
extern_class *obj2;
double arr[3];
};
int main()
{
myClass *OBJ= new myClass();
OBJ->obj1 = new extern_class(arg1...);
OBJ->obj2 = new extern_class(arg2...);
//do something like
OBJ->obj1->extern_fun1(arg1...);
OBJ->obj2->extern_fun2(arg2...);
//delete
delete OBJ;
return 0;
}
I would like to know,
1- in order to free all the objects, is it enough to delete OBJ?
2- is there better ways to write this code?
No, it is not enough. You have to call delete for every new you place in your code explicitely.
Use smart pointers like std::unique_ptr or better, use RAII. To clarify that: smart pointers and RAII are not even only better ways of doing so, they are the ways of doing it correctly in modern C++.
Here's an adequate example with RAII:
#include "extern_lib.h"
class myClass
{
public: // note that public members are possibly bad design (depending on your situation)
extern_class obj1;
extern_class obj2;
double arr[3];
};
int main()
{
myClass foo;
foo.obj1.extern_fun(arg1...);
foo.obj2.extern_fun(arg2...);
return 0;
}
Please note that it's not possible to use RAII in every situation. If you run into such, use smart pointers as stated:
#include "extern_lib.h"
class myClass
{
public: // note that public members are possibly bad design (depending on your situation)
std::unique_ptr<extern_class> obj1;
std::unique_ptr<extern_class> obj2;
double arr[3];
};
int main()
{
myClass foo;
foo.obj1 = std::unique_ptr<extern_class>(new extern_class(arg1...));
foo.obj2 = std::unique_ptr<extern_class>(new extern_class(arg2...));
foo.obj1->extern_fun(arg1...);
foo.obj2->extern_fun(arg2...);
return 0;
}
In order to free all the objects, is it enough to delete OBJ?
No, this will produce a resource leak as the (default) destructor of myClass doesn't care about deleting the pointer members.
Is there better ways to write this code?
Yes, use smart pointers. For example:
class myClass
{
public:
std::unique_ptr<extern_class> obj1;
std::unique_ptr<extern_class> obj2;
double arr[3];
};
In general, try to make resources owned by classes. That is, allocate them in the constructor and deallocate them in the destructor. The standard library's smart pointers will already do that job for you. Avoid managing more than one resource inside a single class.
By the way: If your example is not contrived and you are really not using polymorphism at all, then just get rid of all those news and simply use variables with automatic storage duration. C++ is not Java.
Update: Here is (one way of) how to get rid of new if polymorphism is not needed:
class myClass
{
public:
extern_class obj1;
extern_class obj2;
double arr[3];
myClass(type arg1a, ..., type arg2a, ...) : obj1(arg1a, ...), obj2(arg2a, ...)
// ^^^^ member initializer list ^^^^
{
}
};
The key is to create the member objects as part of the process of creating myClass by using a so-called member initializer list. If you are programming C++11, prefer writing obj1 {arg1a, ...}, obj2 {arg2a, ...} for consistency. (The old syntax still works equally well, however.)
Likewise in your main function:
int
main()
{
myClass mc(arg1a, ..., arg2a, ...); // (1)
mc.obj1.extern_func(...);
mc.obj2.extern_func(...);
return 0; // (2)
}
At line (1), we create an instance of myClass on the stack using our new constructor that will create the members obj1 and obj2 correctly. The compiler-generated default constructor of myClass will correctly destruct mc.obj1 and mc.obj2 as mc goes out of scope on line (2). Again, in C++11 line (1) can be written more cleanly as myClass mc {arg1a, ..., arg2a, ...};.

Memory deallocation of class inside of another class

I am trying to understand how to give back memory if one class creates another class.
I have
Clas A;
Then another class that allocate memory for Class A:
class B{
private:
A* data;
public:
// Allocating new memory
B (){
A* data = new A();
//giving memory back
~B(){
delete data; };
};
And when I execute the code in main function it just crashes. What am doing wrong? I am a bit lost here.
Thanks.
Get rid of the redundant A* in the constructor. What this does is create a new, local variable with the same name as your class member. So the real B::data never gets anything assigned to it, and when you try to delete it, things blow up. To add insult to injury, the new A() you assign to the local data will be leaked (well; it would be leaked if the program didn't crash).
class B{
private:
A* data;
public:
// Allocating new memory
B (){
data = new A();
}
//giving memory back
~B(){
delete data;
}
};
That solves the immediate problem, but as juanchopanza noted in the comments, you will still run into problems if you try to copy this object.
Here's the RAII / Rule of Zero route (assuming your compiler supports C++11)
class A {};
class B {
private:
std::unique_ptr<A> data;
public:
B() : data(new A) {
}
};
The RAII handle in this case a unique_ptr will take care of deallocation for you. Implementing it this means the compiler defined copy constructor, copy assignment operator, move constructor, move assignment operator and destructor will all work fine right out the box.

Array declaration, size definition, and destruction in c++

So I'm unsure as to what the correct way is to do this. I have a class named someClass, with a private variable that is an array of integers. The size doesn't get defined until the constructor is called. Here's how I do it:
In someClass.h:
class someClass {
public:
someClass();
someClass(int size);
~someClass();
private:
int* array;
}
In someClass.cpp:
someClass::someClass() {
array = new int[9];
}
someClass::someClass(int range) {
array = new int[range];
}
someClass::~someClass() {
delete[] array;
}
Did I declare/define the array correctly? Would it have been much better to use a vector?
Is the destructor correct?
Yes, you're doing it correctly (partially), and yes, it would be better to use a std::vector (because of the "partially" part).
The "partially" is that now you will have to provide a copy constructor and copy assignment operator for your class (and for efficiency, you might want to have a move constructor and move assignment operator as well); if you don't, you'll get double deletion errors if you ever copy the class.
std::vector encapsulates all this, so this is why you should prefer it. Not to mention that it has nice features like iterators.
Your class would then look like this:
class someClass {
public:
someClass();
someClass(int size);
//no destructor necessary!
private:
std::vector<int> array;
}
someClass::someClass()
{} // nothing special needed
someClass::someClass(int range) : array(range)
{}
You should also add copy ctor and copy assignment operator. Remember the rule of three!