New to Destructors (C++) [duplicate] - c++

This question already has answers here:
explicit call to destructor is not destroying my object why?
(7 answers)
Closed 6 years ago.
I'm new to destructors, and the tutorials i've been following have been pretty clear up until this point. What actually happens when a destructor is called? Why do I still get values from a destroyed object?
class Box {
public:
Box(double l = 2.0, double b = 2.0, double h = 2.0) { //Constructor
cout << "Box Created" << endl;
length = l;
breadth = b;
height = h;
}
~Box() {
cout << "Box Destroyed" << endl; // Box Destructor
}
double volume() {
return length*breadth*height;
}
private:
double height;
double breadth;
double length;
};
void main() {
Box Box1(10, 15, 5); //Constructors used
Box Box2(5, 15, 20);
cout << "Box1.volume: " << Box1.volume() << endl;
cout << "Box2.volume: " << Box2.volume() << endl;
Box1.~Box(); //Destructors called
Box2.~Box();
cout << "Box1.volume after destruction: " << Box1.volume() << endl;
cout << "Box2.volume after destruction: " << Box2.volume() << endl;
}

You never call a destructor explicitely, unless you know very well you need to because you're handling the life-time and allocation of your objects yourself, which, typically, is a not very C++-like approach.
Destructors are meant to be called automatically, when the lifetime of a C++ objects ends, for example, when an object goes out of scope.
A destructor's job is to "clean up" before the C++ runtime frees the memory associated with that object. Calling a destructor explicitly doesn't "remove" the object – it just brings the object into some kind of "Zombie" state.
As a beginner, generalizing: Don't call destructors explicitely.

Related

Crash Issue - C++ Code Design using pointers and destructors

I have a question regarding the following code, which crashes. I am creating a local variable in testfunction() and then pushing it (variable "y") into a list. This variable has a member pointer "b" of object type Ball. As I understand, this local variable "y" is on the stack, so its' destructor will be called after testfunction() is completed. Also, as I understand, a vector "copies" an object into its' list. From what I've learned, it is best practice to delete a pointer in the destructor if one exists in its' class. So, there is "delete b" in the destructor of Example.
The issue that I am having is that the object y.b is being destroyed at the completion of testfunction(). In main(), I am able to see the value of "name" and the address of "b", but the object "b" has already been deleted. I would like to avoid this.
I think there is an issue with the design of the code/use of pointers vs references, etc. Please guide me in the right direction, I am an idiot!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Ball
{
public:
int a;
Ball()
{
a = 0;
}
~Ball()
{
cout << "destroyed Ball()" << endl;
}
};
class Example
{
public:
string name;
Ball* b;
Example()
{
name = "";
b = NULL;
}
~Example()
{
cout << "destroying Example()" << endl;
delete b;
}
};
void testfunction(vector<Example>& list)
{
cout << "entered testfunction1()" << endl;
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
cout << "y.b->a = " << y.b->a << endl;
list.push_back(y);
cout << "exit testfunction1()" << endl;
}
void testfunction2()
{
cout << "entered testfunction2()" << endl;
Example* y = new Example();
cout << "exit testfunction2()" << endl;
}
int main() {
vector<Example> list;
testfunction(list);
//testfunction2();
if(list[0].b == NULL)
cout << "b is null" << endl;
else
cout << "b is not null" << endl;
cout << list[0].name << endl;
cout << list[0].b << endl;
cout << "list[0].b->a = " << list[0].b->a << endl;
return 0;
}
Since class Example has a pointer member and it tries to own a dynamically allocated resource, it needs non-default copy operations, in other words, it needs user-defined copy constructor and assignment operator.
Inside testfunction, when you copy y into vector, both local y and y copied to the vector point to very same Ball object. The local y is destroyed at the end of the function and Ball is deleted. However, that deleted Ball still pointed by the y in vector
void testfunction(vector<Example>& list)
{
// ...
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
list.push_back(y);
// ...
} // <-- destructor for Example y is called and y.b is deleted
Define a copy constructor and an assignement operator for your class Example.
These shall copy properly your object (creating a duplicated Ball object) when pushed back on the vector.
Example(const Example& a)
{
name = a.name; // attention no dynamic allocation
cout << "copy" <<endl;
if (a.b) {
b = new Ball(*a.b); // create a new duplicated Ball
}
else b = NULL;
}
The problem in your example is that the default copy constructor is called when you pushback the object. It copies memberwise and so the pointer to Ball is copied, not the object pointed to.
Yet another alternative could be to replace your Ball* with shared_ptr<Ball> (and accordingly, new Ball with make_shared<Ball>() and the delete b of the object with a b.reset()). The principle is that this smart pointer keeps track of the number of time the object pointed to is used, so that it will not delete it twice, but only when its no longer used anywhere.

C++ overridden virtual function not getting called [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 9 years ago.
I have the following setup:
main.cpp:
int main()
{
vector <Tour> tourList;
Tour* tour_ptr;
for (unsigned int i = 0; i < tourList.size(); i++)
{
tour_ptr = &tourList[i];
tour_ptr->display();
}
}
Tour.h:
class Tour
{
public:
virtual void display();
};
Tour.cpp:
void Tour::display()
{
cout << "Tour ID: " << getID() << "\n";
cout << "Description: " << getdescription() << "\n";
cout << "Tour Fee: $" << getfee() << "\n";
cout << "Total Bookings: " << getbookings() << "\n\n";
}
GuidedTour.h:
class GuidedTour : public Tour
{
public:
void display();
};
GuidedTour.cpp:
void GuidedTour::display()
{
Tour::display();
cout << "Max Tour Group Size: " << getMaxTourists() << "\n";
cout << "Tour Guide: " << getGuideName() << "\n";
cout << "Tour Date: " << getTourDate() << "\n\n";
}
GuidedTour inherits from the Tour class, and I've specified the display() function as virtual in the base Tour class, but for some reason, the GuidedTour display() function never gets called, only the base function gets called every time. What am I doing wrong?
Your code actually doesn't print anything as the std::vector would initially be empty. Other than that, your problem is caused by object slicing (I'm assuming that you are push_back()ing GuidedTours into the vector).
When object slicing takes place, you are storing only the Tour part of your GuidedTour object(s), and that's the reason why you are seeing the output of Tour::display().
To solve your problem, you need to store the objects polymorphically, by using (smart) pointers and dynamically-allocating your objects.
int main()
{
vector <std::unique_ptr<Tour>> tourList;
for(...) {
tourList.push_back(std::make_unique<GuidedTour>(/* constructor parameters */));
...
tourList.push_back(std::make_unique<Tour>(/* constructor parameters */));
}
for (unsigned int i = 0; i < tourList.size(); i++)
{
tourList[i]->display();
}
}
Notice that I am using std::unique_ptr/std::make_unique and not raw newed pointers. Using them would greatly ease you of the problem of manually managing and deleteing your objects, which sometimes[understatement] are the cause of bugs and undefined behavior.
Note that some people might suggest you to use boost::ptr_vector or something similar. Listen to them, especially if they give you arguments on why they are better than the alternatives.
Your problem has nothing to do with your classes, rather how you are creating the object. Each element in the tourList vector is a tour, and nothing at compile time or runtime is there to determine that they are GuidedTours. In effect, GuidedTour is never called, because I don't see a GuidedTour object in your main anywhere.
I am agree with "It'sPete". because you haven't used the GuidedTour class. It will work if you use the following method.
int main()
{
vector <GuidedTour> tourList;
Tour* tour_ptr;
for (unsigned int i = 0; i < tourList.size(); i++)
{
tour_ptr = &tourList[i];
tour_ptr->display();
}
}

How can I create objects while adding them into a vector?

I have a C++ vector. I want the vector to hold a variable number of objects.
Visual Studio 2012 is giving me an error:
Error: type name is not allowed
From this C++ code:
#include <iostream>
#include <vector>
using namespace std;
class testObject{
private:
int someInt;
public:
testObject(int a){ someInt=a; }
void show() { cout<<someInt<<endl; }
};
int main()
{
vector<testObject> testVector;
cout << "Initial size: " << testVector.size() <<endl;
for ( int i = 0; i < 3; i++ )
testVector.push_back(testObject(3));
cout << "New size: " << testVector.size() << endl;
for ( int j = 0; j < 3; j++ )
testVector[ j ].show();
system("pause");
}
But here's another sample of code that looks the same but it's not working.
void Dealer::setNumberOfPlayers( const int tNumber )
{
for ( int i = 0; i < tNumber; i++ )
vectorOfGamers.push_back(Player); // Player is a class that I created
}
Can I create vector to hold objects of Dealer, Bot and Player at the same time? How do I do that? As I know, all objects in vector should be of one type.
To answer the first part of your question, you must create an object of type Player before you can use it. When you say push_back(Player), it means "add the Player class to the vector", not "add an object of type Player to the vector" (which is what you meant).
You can create the object on the stack like this:
Player player;
vectorOfGamers.push_back(player); // <-- name of variable, not type
Or you can even create a temporary object inline and push that (it gets copied when it's put in the vector):
vectorOfGamers.push_back(Player()); // <-- parentheses create a "temporary"
To answer the second part, you can create a vector of the base type, which will allow you to push back objects of any subtype; however, this won't work as expected:
vector<Gamer> gamers;
gamers.push_back(Dealer()); // Doesn't work properly!
since when the dealer object is put into the vector, it gets copied as a Gamer object -- this means only the Gamer part is copied effectively "slicing" the object. You can use pointers, however, since then only the pointer would get copied, and the object is never sliced:
vector<Gamer*> gamers;
gamers.push_back(new Dealer()); // <-- Allocate on heap with `new`, since we
// want the object to persist while it's
// pointed to
Question 1:
vectorOfGamers.push_back(Player)
This is problematic because you cannot directly push a class name into a vector.
You can either push an object of class into the vector or push reference or pointer to class type into the vector. For example:
vectorOfGamers.push_back(Player(name, id))
//^^assuming name and id are parameters to the vector, call Player constructor
//^^In other words, push `instance` of Player class into vector
Question 2:
These 3 classes derives from Gamer. Can I create vector to hold objects of Dealer, Bot and Player at the same time? How do I do that?
Yes you can. You can create a vector of pointers that points to the base class Gamer.
A good choice is to use a vector of smart_pointer, therefore, you do not need to manage pointer memory by yourself. Since the other three classes are derived from Gamer, based on polymorphism, you can assign derived class objects to base class pointers. You may find more information from this post: std::vector of objects / pointers / smart pointers to pass objects (buss error: 10)?
You cannot insert a class into a vector, you can insert an object (provided that it is of the proper type or convertible) of a class though.
If the type Player has a default constructor, you can create a temporary object by doing Player(), and that should work for your case:
vectorOfGamers.push_back(Player());
I know the thread is already all, but as I was checking through I've come up with a solution (code listed below). Hope it can help.
#include <iostream>
#include <vector>
class Box
{
public:
static int BoxesTotal;
static int BoxesEver;
int Id;
Box()
{
++BoxesTotal;
++BoxesEver;
Id = BoxesEver;
std::cout << "Box (" << Id << "/" << BoxesTotal << "/" << BoxesEver << ") initialized." << std::endl;
}
~Box()
{
std::cout << "Box (" << Id << "/" << BoxesTotal << "/" << BoxesEver << ") ended." << std::endl;
--BoxesTotal;
}
};
int Box::BoxesTotal = 0;
int Box::BoxesEver = 0;
int main(int argc, char* argv[])
{
std::cout << "Objects (Boxes) example." << std::endl;
std::cout << "------------------------" << std::endl;
std::vector <Box*> BoxesTab;
Box* Indicator;
for (int i = 1; i<4; ++i)
{
std::cout << "i = " << i << ":" << std::endl;
Box* Indicator = new(Box);
BoxesTab.push_back(Indicator);
std::cout << "Adres Blowera: " << BoxesTab[i-1] << std::endl;
}
std::cout << "Summary" << std::endl;
std::cout << "-------" << std::endl;
for (int i=0; i<3; ++i)
{
std::cout << "Adres Blowera: " << BoxesTab[i] << std::endl;
}
std::cout << "Deleting" << std::endl;
std::cout << "--------" << std::endl;
for (int i=0; i<3; ++i)
{
std::cout << "Deleting Box: " << i+1 << " (" << BoxesTab[i] << ") " << std::endl;
Indicator = (BoxesTab[i]);
delete(Indicator);
}
return 0;
}
And the result it produces is:
Objects (Boxes) example.
------------------------
i = 1:
Box (1/1/1) initialized.
Adres Blowera: 0xdf8ca0
i = 2:
Box (2/2/2) initialized.
Adres Blowera: 0xdf8ce0
i = 3:
Box (3/3/3) initialized.
Adres Blowera: 0xdf8cc0
Summary
-------
Adres Blowera: 0xdf8ca0
Adres Blowera: 0xdf8ce0
Adres Blowera: 0xdf8cc0
Deleting
--------
Deleting Box: 1 (0xdf8ca0)
Box (1/3/3) ended.
Deleting Box: 2 (0xdf8ce0)
Box (2/2/3) ended.
Deleting Box: 3 (0xdf8cc0)
Box (3/1/3) ended.
// create a vector of unknown players.
std::vector<player> players;
// resize said vector to only contain 6 players.
players.resize(6);
Values are always initialized, so a vector of 6 players is a vector of 6 valid player objects.
As for the second part, you need to use pointers.
Instantiating c++ interface as a child class

How is this code running?

Here is the code first, it comes from 'Ruminations on C++' chapter 10
// TestCode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
class P_Node
{
friend class Picture;
protected:
P_Node() : use(1)
{
}
virtual ~P_Node()
{
}
private:
int use;
};
class Picture
{
friend Picture frame(const Picture&);
public:
Picture() : p(new P_Node)
{
cout << "Constructor\t" << "Picture::Picture()" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
}
Picture(const Picture& orig) : p(orig.p)
{
cout << "Copy Constructor\t" << "Picture::Picture(const Picture&)" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
orig.p->use++;
}
~Picture()
{
cout << "Destructor\t" << "Picture::~Picture()" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
cout << "Deleted" << endl;
delete p;
}
}
Picture& operator=(const Picture& orig)
{
cout << "operator=\t" << "Picture& Picture::operator=(const Picture& orig)" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
orig.p->use++;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
delete p;
}
p = orig.p;
return *this;
}
private:
Picture(P_Node* p_node) : p(p_node)
{
// Why not p_node->use++?
cout << "Picture::Picture(P_Node* p_node)\tcalled" << endl;
}
P_Node *p;
};
class Frame_Pic : public P_Node
{
friend Picture frame(const Picture&);
private:
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
Picture p;
};
Picture frame(const Picture& pic)
{
return new Frame_Pic(pic);
}
int main(int argc, char* argv[])
{
Picture my_pic;
frame(my_pic);
return 0;
}
The result is:
Constructor Picture::Picture() called
Picture p count 1
Copy Constructor Picture::Picture(const Picture&) called
Picture p count 1
Frame_Pic::Frame_Pic(const Picture& orig) called
Picture::Picture(P_Node* p_node) called
Destructor Picture::~Picture() called
Picture p count before decrease 1
Picture p count after decrease 0
Deleted
Destructor Picture::~Picture() called
Picture p count before decrease 2
Destructor Picture::~Picture() called
Picture p count before decrease 1
Picture p count after decrease 0
Deleted
I have two questions about this code:
Why is the copy constructor called before Frame_Pic's Constructor? In my mind, the copy constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.
In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?
Thanks for any help.
I'm using VC6 under Windows XP.
1, Why is the Copy Constructor called before Frame_Pic's Constructor?
Because the p member is being copy-constructed in the initialization list of Frame_pic's constructor. The initialization list runs before the constructor's body is entered.
In my mind, the Copy Constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.
frame() is declared to return a Picture instance by value, but it is coded to return a Frame_pic* instead. Frame_pic derives from P_node, and Picture has a constructor that accepts a P_node*, and that constructor is accessible to frame() so the compiler allows it.
2, In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?
The use count is on P_node, not Picture. The Picture that frame() returns owns the Frame_pic that frame() creates, whose use count member is already 1 by the Frame_pic constructor. That is why that Picture constructor does not increment the use count - it is already at the correct value.
The Frame_pic contains its own Picture that is copy-constructed from another Picture, so that Picture constructor needs to increment the use count of the original Picture.
The copy constructor is invoked by Frame_Pic's constructor (it's invoked by the initializer : p(pic)). However Frame_Pic's constructor doesn't print until after all initializers have been run.
Because the intended use of the constructor is not documented, it's hard to say. It may be a bug, or it may be 'attach semantics' - that is, it may be considering the case where you take manual control of the P_Node*, then later give it back. However attach semantics is unlikely, as there's no corresponding detach mechanism to return the pointer and clear it without decrementing the refcount. So, most likely a bug.
Note that while this sort of manual reference counting can be good as a learning exercise, modern C++ code generally uses smart pointers (eg, std::shared_ptr or boost::shared_ptr, invasive_ptr, etc) to automate the process.
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
You initializing 'p' using its copy constructor 'p(pic)', hence it gets called in the order you see

Newb C++ Class Problem

I am trying to get a grasp on pointers and their awesomeness as well as a better C++ understanding. I don't know why this wont compile. Please tell me what is wrong? I'm trying to initialize the pointer when an instance of the class is created. If I try with a normal int it works fine but when I tried to set it up with a pointer i get this in the console
Running…
Constructor called
Program received signal: “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
Any assistance is appreciated greatly.
Here is the code
#include <iostream>
using namespace std;
class Agents
{
public:
Agents();
~Agents();
int getTenure();
void setTenure(int tenure);
private:
int * itsTenure;
};
Agents::Agents()
{
cout << "Constructor called \n";
*itsTenure = 0;
}
Agents::~Agents()
{
cout << "Destructor called \n";
}
int Agents::getTenure()
{
return *itsTenure;
}
void Agents::setTenure(int tenure)
{
*itsTenure = tenure;
}
int main()
{
Agents wilson;
cout << "This employees been here " << wilson.getTenure() << " years.\n";
wilson.setTenure(5);
cout << "My mistake they have been here " << wilson.getTenure() <<
" years. Yep the class worked with pointers.\n";
return 0;
}
You don't ever create the int that the pointer points to, so the pointer is pointer to an area of memory that doesn't exist (or is used for something else).
You can use new to get a block of memory from the heap, new returns the address of the memory location.
itsTenure = new int;
So now itsTenure holds the memory location you can dereference it to set its value.
The changed constructor is as follows:
Agents::Agents()
{
cout << "Constructor called \n";
itsTenure = new int;
*itsTenure = 0;
}
But you must also remember to delete it using delete
Agents::~Agents()
{
cout << "Destructor called \n";
delete itsTenure;
}
You are just missing a new, in the constructor.
itsTenure = new int;
You don't need to make this a pointer, however. Why are you?
You have to allocate a block of memory for your int, and only then use the address of this block of memory (the pointer). This is done with new :
cout << "Destructor called \n";
itsTenure = new int;
*itsTenure = 0;
Then you have to release the memory in the destructor with delete:
cout << "Destructor called \n";
delete itsTenur;
*itsTenure = 0 does not initialize the pointer. It writes 0 to the location that itsTenure points to. Since you never specified where itsTenure points to, that might be anywhere and the behaviour is undefined (an access violation like you're getting being the most likely result).
You need to allocate memory for *tenure in the constructor:
Agents::Agents()
{
cout << "Constructor called \n";
itsTenure = new int;
*itsTenure = 0;
}