C++ A constructor triggers a destructor - c++

I'm trying to make a Monster generator using vectors and classes to allow the user to create and delete Monster objects as they wish. However, when I call the constructor of Monster in my code it also immediately triggers a destructor, thereby removing Monster from the the vector container.
This is the fragment of my code, which creates and destroys the Monster object:
while (p == 't')
{
cout << "Generate (g) or remove (u) a monster?" << endl;
cin >> p;
while (p == 'u' && Monster::n == 0)
{
cout << "No monsters to remove." << endl;
cout << "Generate (g) or remove (u) a monster?" << endl;
cin >> p;
}
while (p != 'g' && p != 'u')
{
cout << "Error. Follow the instructions." << endl;
cout << "Generate (g) or remove (u) a monster?" << endl;
cin >> p;
}
if (p == 'g')
{
{
vec.push_back(Monster());
vec[Monster::n].print();
}
}
if (p == 'u')
{
vec.~Monster();
}
cout << "Continue (t) or finish (n)?" << endl;
cin >> p;
while (p != 't' && p != 'n')
{
cout << "Error. Follow the instructions?" << endl;
cout << "Continue (t) or finish (n)?" << endl;
cin >> p;
}
This is the constructor for Monster:
Monster::Monster()
{
ostringstream buffer;
buffer << Monster::n;
string name = buffer.str();
Monster::setname(name);
Monster::settype(MonsterType(rand() % 7 + 1));
Monster::setattack(rand() % 25);
Monster::sethealth(rand() % 15);
cout << endl << "Monster generated." << endl << endl;
Monster::n++;
}
This is the destructor:
Monster::~Monster()
{
cout << "Monster removed." << endl << endl;
Monster::n--;
}
When I input the character 'g', it creates a Monster object as expected but then immediately destroys it, even before its stats are printed with the print() method. This means my code is not acting as expected, as it will never allow the proper creation or destruction of Monster objects.
Can someone please help me understand what's going on here?
EDIT:
Alright, I was able to somewhat solve the issue by making another constructor.
This is it:
Monster::Monster(const Monster & mon)
{
Monster::name = mon.name;
Monster::type = mon.type;
Monster::attack = mon.attack;
Monster::health = mon.health;
cout << endl << "Monster created (cpy)." << endl << endl;
Monster::n++;
}
I edited the point where the user decides to generate a Monster to the following:
{
vec.push_back(Monster());
vector<Monster> veccpy = {};
veccpy.push_back(Monster(vec[Monster::n-1]));
vec.back().print();
}
When I lauch the program, it spits out something like this:
Monster created
Monster created (cpy)
Monster removed
Monster created (cpy)
Monster created (cpy)
Monster removed
Monster's stats
Now, the odd thing is even though it uses those constructors so oddly, the program works as I intended it to. n iterates as it should, I can remove or add Monster as I intended and the Monster stats are displayed as they should.
Could someone point to what I'm doing wrong here?

In this line:
vec.push_back(Monster());
You are creating a temporary object of type Monster, which is being copied to the vec. Because it is a temporary object it will be destroyed right after the statement ends at the semicolon. It will be destroyed after it was copied to vec.
vec.~Monster();
This surely does not compile, if you wanted to clear your vector then use vec.clear()
In your code when you write Monster::setname(name);
most programmers will think you are setting a static variable. I hope you don't keep name of your monster as a static variable.
Another thing you need to fix in your code is to make sure it adheres to the rule of three (as it was in comments). Your Monster::n variable is a kind of resource which is being managed by Monster class, and to correctly manage it you need to appropriately modify it in all the constructors and operators which might create/destroy Monster class instance. Without describing it with long text below is a sample code which presents which constructors/operators are bing called in your code:
http://coliru.stacked-crooked.com/a/9184f137b7a90995
struct Monster {
Monster() { std::cout << n << ":" << __PRETTY_FUNCTION__ << "\n"; n++; }
~Monster() { std::cout << n << ":" << __PRETTY_FUNCTION__ << "\n"; n--; }
Monster(const Monster&) { std::cout << n << ":" << __PRETTY_FUNCTION__ << "\n"; n++; }
Monster& operator=(const Monster&) { std::cout << n << ":" << __PRETTY_FUNCTION__ << "\n"; n++; return *this; }
static int n;
};
int Monster::n;
int main()
{
{
std::vector<Monster> vec;
std::cout << "-------------- START\n";
vec.push_back(Monster());
std::cout << "-------------- END\n";
}
std::cout << Monster::n; // should output 0
}
-------------- START
0:Monster::Monster() // temporary created
1:Monster::Monster(const Monster&) // vector element is copy constructed
// from temporary here you have missed Monster::n++
2:Monster::~Monster() // temporary monster destroyed
-------------- END
1:Monster::~Monster() // this is a vector being destroyed
0 // this should always be 0, otherwise
// still something is missing.

vec.push_back(Monster());
This is going to create a temporary object, an instance of the Monster class, and pass it to the vector's push_back() method.
push_back() will take its parameter and copy it into the vector. Since the vector owns its object, this will involve the construction of another instance of the Monster class.
After push_back() returns the temporary object that it passed as the parameter is going to get destroyed, thus invoking your object's destructor. And that's why you see a destructor getting invoked here.
Note that when adding objects to a vector, the vector may choose to reallocate its contents, at any time. This will involve, essentially, copy-constructing new instances of the class in the vector, then destroying the old ones, as well.
Lessons learned
Spend some time reading your C++ book and learn how smart pointers work, and put smart pointers in your vector, rather than object instances, in order to avoid unwanted side effects due to temporaries.
You could also implement move constructors as an alternative solution, but using smart pointers will probably be easier.
A second alternative is to emplace_back(), rather than push_back() new instances. However that won't solve your problem completely. See "reallocation", above.
Additionally, it wouldn't hurt to make your class Rule of 3 compliant either. The real underlying reason you asked this question is likely because it's currently not.

What you are seeing is expected and it's happening because you have defied the vec as std::vector<Monster>. What does it means that you are declaring the vector that would contains the objects of Monster class.
Now the way vector works is that they need to keep all those Monster class objects alive unless you remove them from the vector. Which means, the scope of those Monstors object should be equivalent till the Object remains the vector.
Having said that, now if you look at this line of code vec.push_back(Monster());, the new Monster object hat you are declaring will have the scope till the scope of braces with in the if, and as soon it it will be out of scope, it will not be accessible. Which is why, when the push_back gets executed, it copies the given Monster object (by executing its default copy constructor, or custom one if any), and create a new object for the vector.
If you don't want to the object to be copied, what you do is as follow:
Declare vector as std::vector<std::unique_ptr<Monster>> and
call push_back as .push_back(make_unique<Monster>()).
Here instead of declaring the Monster on the local stack, you are declaring it on the Heap and using the smart pointer to manage the life of the object on the heap.

Related

storing an object name during construction of another object

I wanted to create objects from the class “takeSnapshots” that would learn, upon their instantiation, the name of another object from the class “lock” that they could query later as the state of the “lock” object changes. I can think of multiple ways of letting the object from class “takeSnapshots” know which object it is to query (like including the name of the “lock” object as part of the call to its member functions). But, I thought it better to take care of the relation in the beginning and not worry later if I am calling the correct object combinations.
The included code shows stripped down versions of the two classes and example instantiations created in main.
I have included the outputs on each line following their respective couts.
What I expected was that the constructor of “takeSnapshots” would store away the address of the “lock” object. Then I could use it later when taking a snapshot. You can see that what gets stored away (at least when I use it to get numWheels) is a few addresses off from the address that the “lock” object thinks it has for numWheels.
I am mostly interested in knowing why this code does not work the way I expect, i.e, if this is not a good architectural idea, that is one thing. But with the behavior I’m seeing here, I’m clearly not ready to use pointers in anything complicated and I don’t want to give up on the basic architecture just because of erroneous implementation. Any help would be greatly appreciated.
// simpleTest.cpp : Demonstrates problem I'm having understanding
// pointer to an object.
#include "stdafx.h"
#include<iostream>
using namespace std;
class lock {
public: //Just while I run a test.
int numWheels;
lock(int numW) {
numWheels = numW;
cout << " \n In \"lock\" constuctor, address and value of numWheels
" << &numWheels << " " << numWheels << endl;
} //Values from console: 0034F874 and 4
};
class takeSnapshots {
lock* localLock;
public:
takeSnapshots(lock myLock) {
localLock = &myLock;
cout << " \n In \"takeSnapshots\" constuctor, address and value of
numWheels " << &localLock->numWheels << " "
<< localLock->numWheels << endl;
//Values from console: 0034F794 and 4 "Same value, but not the same
//address as expected from "lock."
}
void takeASnapSnapshot() {
cout << " \n When taking a snapshot, address and value of numWheels
" << &localLock->numWheels << " " << localLock->numWheels <<
endl;
//Values from console: 0034F794 and 2303449 "No longer even the
// same value as expected from "lock."
}
};
int main()
{
lock yourLock(4);
takeSnapshots myShots1(yourLock);
cout << " \n In main (from \"yourLock\"), address and value of
numWheels " << &yourLock.numWheels << " " << yourLock.numWheels <<
endl;
//Values from console: 0034F874 and 4 "Still the same values as set
//in the constructor of "lock."
//Take a picture
myShots1.takeASnapSnapshot();
return 0;
}

Using a map that has a abstract base class pointer and calling a derived class function

I've searched on the web and can't find any solutions to my problem I hope you can help.
So I have constructed an abstract base class and have two derived classes that represents different experiments. (one is actually a derived derived class of my base class) And I made a map as such in a separate header file to store different types of experiments.
//Map class template to store name of experiment and the experiment within a project
typedef map <string, baseData <double>*> ExpContainer;
void search(string searchName, ExpContainer exps) {
ExpContainer::iterator Iter;
Iter = exps.find(searchName); //finds the entry corresponding to searchName and returns the iterator
if (Iter != exps.end()) { //need this as if entry is not found, the return will be end iter.
cout << "Found the experiment " << Iter->first << "." << endl;
Iter->second->print();
}
else {
cout << "Sorry, experiment " << searchName << " is not found" << endl;
}
}
The print() function is different for each experiment type and I know there's a problem called slicing so I've made sure that print() is virtual in the base class. Here's my base class:
namespace mynmsp {
//base class of data can be measurements or errors
template < class T> class baseData {
public:
virtual void print() =0;
virtual ~baseData() {
cout << "Destructor called for the base class." << endl;
}
};
}
Then in my main.cpp I've constructed different types of experiment and I want to print them. Each experiment class has different implementation of the print function that overrides the print function from the base class, like:
void print(){ //do something };
And in my main.cpp I have the map defined as:
ExpContainer project;
And after I have constructed each experiment, I've asked the user for the name of the experiment (expName) and inserted into project as such:
project[expName] = &expC;
I think the insertion is fine as I tested the size of project and it was correct.
However, a runtime error occured when my search function was called like this:
search(name, project);
I don't know if there's a problem with slicing or with my pointers?
I tried to make print() a virtual function in each derived class but that doesn't seem to work either.
Apologies for the long question, please help!
Edit: I've constructed my experiments inside a do while loop while project is declared outside. The whole code is very long but its basics is something like this:
string repeatstr; //user input whether to repeat do while loop or not
bool repeat = true; //condition for staying inside do while loop
ExpContainer project; //declared project to store experiments
do {
string expName;
string ans1; //character to store user input
cout << "What is the name of your experiment? " << endl;
cin >> expName;
cout << "Is this a experiment C ? (y/n)" << endl;
cin >> ans1;
if(ans1 =="y"){
//call the constructor for expC
project[expName] = &expC;
}else {
//call the constructor for expB
project[expName] = &expB;
}
cout << "Do you want to enter another experiment? (y/n)" << endl;
cin >> repeatstr;
if (repeatstr == "n") { repeat = false; }
}while (repeat); //loop over this do-while loop while repeat is true
cout << "There are " << project.size() << " in this database." << endl;
//to retrieve info from a certain experiment
string input, name;
cout << "Would you like to retrieve any experiments (y/n)? " << endl;
input = EitherInput("y", "n");
if (input == "y") {
cout << "Please enter the name of the experiment you want to retrieve: " << endl;
cin >> name;
search(name, project); //code breaks down here!
}
You are saving a pointer to the object that was already destroyed. You can check the addresses that you have in the map, most probably they are the same. You should store your experiment object in dynamic memory
if(ans1 =="y")
{
project[expName] = new expC();
} // Scope ends here and all variable created in it will be destroyed.
else
{
project[expName] = new expB();
} // Scope ends here and all variable created in it will be destroyed.
And after you are done with them you need to call delete on each pointer to avoid memory leak. Also you need to check if the items in the map are already existing, otherwise you will loose pointers to allocated memory which is automatically a memory leak.
I would recommend you to use std::share_ptr< baseData<double> > instead of bare baseData<double>*. Here you can read more about it. And also consider using typedef in order to have more clear syntax.
P.S.
The function
void search(string searchName, ExpContainer exps)
will copy whole map to its body. Use constant reference instead
void search(string searchName, const ExpContainer& exps)
But then you'll also need to declare function print as const:
virtual void print() const = 0;
and override it with const modifier:
virtual void print() const override;
And use constant iterator ExpContainer::const_iterator Iter

How do I access objects from a vector of "pointer-to-objects" in c++

I'm writing a program that creates a vector of pointer-to-objects.
How do I access the individual objects that the pointers reference from the pointer-to-objects vector?
I'm trying to call the speak() function in the class Object for each of the objects that the pointers inside the vector reference.
Thank you for your time
class Object
{
public:
void speak()
{
cout<<"Hello!"<<endl;
}
};
int main()
{
int choice;
vector<Obj*> objVector; //create empty vector of "pointer-to-object"
Object* ptrObj; //point to object
while (choice!=5)
{
cout <<"1.Create Object\n";
cout <<"2.Destroy Object\n";
cout <<"3.Print number of existing Objects\n";
cout <<"4.Tell existing Objects to say Hello\n";
cout <<"5.Quit Program"<<endl;
cout <<"Please enter your choice: ";
cin >> choice;
if (choice==5)
cout <<"\nProgram is quitting\n"<<endl;
else if (choice==1)
{
ptrObj= new Object;
ObjVector.push_back(ptrObj); //adding an Object object
}
else if (choice==2) //remove object
{
objVector.pop_back();
}
else if (choice==3)
{
cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
}
else if (choice==4)
{
for (int i=0; i<objVector.size(); i++)
{
????????????
}
}
}
return 0;
}
In your existing code, you can access the pointer exactly the way you use it elsewhere in code:
Object* obj = objVector[i];
obj->speak();
// or, simply:
objVector[i]->speak();
Using the operator -> is simply another way to say (*objVector[i]).speak().
Alternatively, the idiomatic approach to writing the loop would look like this:
for(vector<Object*>::iterator it = objVector.begin(); it != objVector.end(); ++it) {
// iterators work like another level of pointers, and need to be dereferenced:
(*it)->speak();
}
If your compiler supports C++11, you can rewrite the loop like this:
for(auto it = std::begin(objVector); it != std::end(objVector); ++it) {
(*it)->speak();
}
Or like this, using range-based for, which dereferences the iterator for you:
for(auto& obj : objVector) {
obj->speak();
}
As an aside, there are cases where you will not be sure whether objVector[i] is even in the vector at all, and accessing it may crash your program or even cause demons to fly forth from your nasal cavity.
For added safety, you can reference positions in your vector with the at function, like so:
try {
for (int i=0; i<objVector.size(); i++)
{
Object* obj = objVector.at(i);
obj->speak();
}
} catch (const std::out_of_range& ex) {
cerr << "no object at position " << i << " in objVector" << endl;
cerr << "objVector says " << ex.what() << endl;
}
Notice, though, that this is a lot slower, although it gives you a chance to handle the problem in the catch block. The try block will run the loop and stop and run the catch block if the at function throws an exception - which will be an exception of type out_of_range. Note also that using [i] will not do the same thing, because it does not throw an exception - it doesn't even bother to check if i is within the length of the vector. This happens to also be why [i] is faster than .at(i).
Finally, also notice that the loops using iterators cannot encounter this particular problem, so long as you don't try to use the iterators after adding or removing something from the vector.
The easiest way is to use *(objVector[i])
To access speak, objVector[i]->speak is just shorter.
You can dereference them with *. Like *(ObjVector[i])
But if you just need to call a method of object you can do it with ->
ObjVector[i]->speak()
Unrelated to the question, but I drop some comment to revise the program.
As others pointed out, you can call object function from pointer contained on vector with doing objVector[i]->speak().
However, as #greyfade pointed out, there is leaking memory issue. You have to delete object when the object is created by new. You can delete object by delete like this,
Object* ptr = objVector.back();
objVector.pop_back();
delete ptr;
To erase memory leaking issue, you can store Object object directly in objVector instead of Object*. In this way, you don't have to worry about deleting objects. You can do like this,
int main()
{
int choice;
vector<Object> objVector; //create empty vector of "pointer-to-object"
while (choice!=5)
{
cout <<"1.Create Object\n";
cout <<"2.Destroy Object\n";
cout <<"3.Print number of existing Objects\n";
cout <<"4.Tell existing Objects to say Hello\n";
cout <<"5.Quit Program"<<endl;
cout <<"Please enter your choice: ";
cin >> choice;
if (choice==5)
cout <<"\nProgram is quitting\n"<<endl;
else if (choice==1)
{
objVector.emplace_back(); //adding an Object object
}
else if (choice==2) //remove object
{
objVector.pop_back();
}
else if (choice==3)
{
cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
}
else if (choice==4)
{
for (auto& obj : objVector)
{
obj.speak();
}
}
}
return 0;
}
This code is using c++11 feature. You can add object by calling emplace_back and delete object by just calling pop_back(). Isn't this sweet?
And one more thing. You forgot some code on header. This code cannot be compiled without these headers,
#include <iostream>
#include <vector>
using namespace std;
I'd happy if this code helps you.

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.

Pointer to base class lost in while loop, causing segfault. C++

This code uses a while loop to get user input and execute the appropriate command - I've reduced it to 2 commands for sake of brevity.
The Oblock object is created correctly (command "O"), as is the pointer to the base class. It appears that the calls to both objects work correctly as well.
However, after returning to the while loop, the pointer to the object appears to be lost, and attempting to access its members (command "t") causes a segfault.
I've included the example code below - my questions are afterwards.
#include<vector>
#include<iostream>
#include<string.h>
using namespace std;
class Tetramino {
private:
int squareSize;
vector<string> myShape;
public:
void setValues(int size) {
squareSize = size;
myShape = vector<string> ((size*size), ".");
}
string getValues(int i) {
return myShape[i];
}
int getSize() {
return squareSize;
}
};
class Oblock : public Tetramino {
public:
Oblock() {
setValues(2);
}
};
main () {
string input;
bool runProgram = true;
Tetramino *pBlock;
while (runProgram) {
cin >> input;
if (input == "O")
{
Oblock myBlock;
cerr << "0thi: " << myBlock.getValues(0) << endl;
Tetramino *pBlock = &myBlock;
cerr << "0thi: " << pBlock->getValues(0) << endl;
}
if (input == "t")
{
cerr << "0thi: " << pBlock->getValues(0) << endl;
}
}
return 0;
}
Are objects deconstructed upon exiting the if statements?
Is there perhaps a better way to repeatedly get user input?
Thanks in advance for any advice! I searched for questions similar to this one and couldn't find one appropriate for my needs.
Tetramino *pBlock is local within its scope. You're shadowing over the one in main with the one within the if.
Also, myBlock is local and will be destructed - you'll have a dangling pointer. You should allocate with new (and delete...)
Instead of Tetramino *pBlock = &myBlock; do pBlock = new Oblock; when you handle the "O" input (and handle delete pBlock of the previous one).
if (input == "O")
{
Oblock myBlock;
cerr << "0thi: " << myBlock.getValues(0) << endl;
Tetramino *pBlock = &myBlock;
cerr << "0thi: " << pBlock->getValues(0) << endl;
}
An object with automatic storage duration (commonly called a function-local variable) has a lifetime beginning after its declaration and ending at the end of the nearest enclosing block } token. So myBlock is destroyed at the end of this if statement, and can't be used again.
Also note that you have declared two different pointers named pBlock. Assigning the inner one does nothing to the earlier one, which is still uninitialized.
Answering your first question: Yes, the statement
Oblock yblock;
Creates an instance of Oblock on the stack. It is destroyed when the code leaves the respective block, so any pointers to it become invalid after that. To create an object that lives as long as you wish, use new to create the object on the heap.
Your pointer becomes garbage after myBlock goes out of scope (where the if statement closes) which will be causing the segmentation fault when you try to access it later
if(input == "O"){
Oblock myBlock;
}
^^^^ right here myBlock becomes garbage
Also, if a user inputs "t" before "O" it will cause a segmentation fault because they will be trying to access an uninitialized pointer. You should probably get that looked at.