I learned that one of the motivation for copy constructor using is to avoid of the follow crash in the program -
#include <iostream>
using namespace std;
class Employee {
public:
Employee(int ID,char const * name){...};
~Employee(){...};
// Methods
void Print();
private:
// members
int m_ID;
char* m_name;
};
void MyFunc(Employee emp) {
cout << "in MyFunc \n ";
}
int main() {
Employee One(1,"Garen Torosian");
// calling copy constructor
MyFunc(One);
cout << "In the end of main \n";
// Here the program crashes!
return 0;
}
as you can see the program should be crash before the return 0; , but when I run that program it works fine and terminated ok , why ?
Edit : In this case the program indeed crash -
// Employee.h
#include <iostream>
using namespace std;
class Employee {
public:
Employee(int ID,
const char* name);
~Employee();
// Methods
void Print();
private:
// members
int m_ID;
char* m_name;
};
// Employee.cpp
#include "Employee.h“
Employee::Employee(int iID, const char *name){ // Ctor
cout << "Constructor called" << endl;
m_ID = iID;
m_name = new char [strlen(name) +1];
strcpy(m_name, name);
Print();
}
void Employee::Print() { // Print
cout << "ID: " << m_ID << ",Name:” << m_name
<< " ,Address(pointer):0x" << hex << (int) m_name<< endl;
}
Employee::~Employee() { // Dtor
cout << "Destructor called"<<endl;
Print();
delete [] m_name;
m_name=NULL;
}
void MyFunc(Employee emp) {
cout << "in MyFunc \n ";
}
int main()
{
Employee One(1,"Eli Rachamim");
// calling copy constructor
MyFunc(One);
cout<< "In the end of main \n“;
// Here the program crashes!
return 0;
}
If you d-tor is like
~Employee(){ delete[] name; }
and you alloc memory for your char* pointer, and you have no copy c-tor, than copy c-tor generated by compiler, that do memberwise-copy, will be called when you copy object. So, there will be double-free, that in most cases give you memory dump (in real calling destructor to already destructed object is UB and calling delete[] on already deleted object is also UB). But if you don't work with memory - copy c-tor, generated by compiler works well.
EDIT.
So, your second example demonstrates call of d-tor to allready destructed object and also double-free.
Why do you think it should crash?
C++ has the unfortunate feature of supplying an automatically-generated copy-constructor if you don't provide one, and your MyFunc() doesn't really do anything that would get screwed by that auto-generated copy.
Related
I have this simple class with two specialized constructors.
#include <iostream>
class test_01
{
std::string name;
uint16_t value;
public:
test_01(std::string name);
test_01(uint16_t value);
~test_01();
void show_message(std::string message);
};
test_01::test_01(std::string name)
{
std::cout << "Constructor string is called" << std::endl;
test_01::name = name;
}
test_01::test_01(uint16_t value)
{
std::cout << "Constructor uint16 is called" << std::endl;
test_01::value = value;
}
test_01::~test_01()
{
std::cout << "Destructor is called" << std::endl;
}
void test_01::show_message(std::string message)
{
std::cout << message.c_str() << std::endl;
}
int main()
{
bool result = true;
test_01 t = result ? test_01("test") : test_01(57);
t.show_message("hello");
}
Each constructor is called depending on an external condition. When the ternary operator is executed a destructor is called. Thus.
Constructor string is called
Destructor is called
hello
Destructor is called
I don't understand why the first destructor is called
Thanks !
Because there are two test_01 objects created, so two must be destroyed.
first is exactly one of
vvvvvvvvvvvvvvv or vvvvvvvvvvvv
test_01 t = result ? test_01("test") : test_01(57);
^ second is here
Had you added logging to the copy or move constructors, you would see, a temporary object is copied/moved into t object, which is move/copy constructed from this temporary.
I am trying to understand why my code doesn't use destructor of class Name. In fact I write two classes. First one called Name and a second called Person that have a pointer to object Name. What I don't understand is why the program doesn't called to the destructor of Name, because I think when I write "new" I create a new object so it has to call to the destructor of class Name before closing program.
Can you explain what wrong in my understanding. Thanks !
class Name
{
private:
string name;
public:
Name(string name) : name(name) { cout << "Hello " << name << endl; }
~Name() { cout << "See you soon " << name; }
};
class Person
{
private:
Name* myname;
public:
Person(string name) { myname = new Name(name); }
~Person() { cout << "Exit" << endl; }
};
int main()
{
Person("Marc");
Person("Alex");
}
You are creating a memory leak here, because you create a new instance of Name here
Person(string name) { myname = new Name(name); }
but you never delete it. This is the reason why the destrcutor of Name is never called.
To avoid this you can use an std::unique_ptr or an std::shared_ptr, which will automatically handle the lifetime of such an object.
std::unique_ptr<Name> myname;
Person(string name) { myname = std::make_unique<Name>(name); }
An alternative is to delete the object in your destructor, but in C++ you should avoid direct handling of dynamic raw pointers.
#include <iostream>
#include <memory>
class Name
{
private:
std::string name;
public:
Name(std::string name) : name(name) { std::cout << "Hello " << name << std::endl; }
~Name() { std::cout << "See you soon " << name << std::endl; }
};
class Person
{
private:
std::unique_ptr<Name> myname;
public:
Person(std::string name) { myname = std::make_unique<Name>(name); }
~Person() { std::cout << "Exit" << std::endl; }
};
int main(int argc, char **argv)
{
Person("Marc");
Person("Alex");
return 0;
}
As myname object in Person's class is a pointer. For every pointer there must be a delete statement to deallocate the memory.
Replace Person's class Destructor as:
~Person() {
cout << "Exit" << endl;
delete myname;
}
Read the comments too.
Basically, I am trying to figure out object constructors, destructor, and classes. I created a class with a few public member variables, and a few private member variables. At this point I am only utilizing the public members within my code.
My question is, to put it quite simply, how do I utilize the constructor, destructor, and print off the objects info to the console.
Thanks.
#include <iostream>
// Class -> NPC
// Contains generic stats for an NPC in a game
class NPC
{
public:
char name;
int age;
char favoriteItem;
private:
char quest;
char nemesis;
int karma;
}
// Object Constructor
NPC::NPC (char newName, int newAge, char newFavoriteItem)
{
name = newName;
age = newAge;
favoriteItem = newFavoriteItem;
}
// Object Deconstructor
NPC::~NPC()
{
// Do nothing
}
// Here I would like to create a new NPC, bob, with a name of "Bob", age of 28, and his favorite items being a Sword
// Next, I attempt to use this information as output.
int main()
{
NPC bob("Bob",28, "Sword");
std::cout << bob << std::endl;
}
Fixed the char (only one character) to std::string. I added initialization list and std::ostream &operator << operator.
http://en.cppreference.com/w/cpp/language/default_constructor
#include <iostream>
#include <memory>
#include <string.h>
class NPC
{
public:
std::string name;
int age;
std::string favoriteItem;
NPC(std::string const& name, int age, std::string favoriteItem)
: name(name), age(age), favoriteItem(favoriteItem)
{};
private:
char quest;
char nemesis;
int karma;
};
std::ostream &operator << (std::ostream &os, NPC const& npc)
{
os << npc.name << " " << npc.age << " " << npc.favoriteItem << "\n";
return os;
};
int main()
{
NPC npc("Bob", 28, "Sword");
std::cout << npc;
return 0;
}
#include <iostream>
using namespace std;
class teacher{
private:
int Tnum;
public:
teacher(){
Tnum = 0;
}
teacher(int n){
cout << "creating teacher"<<endl;
Tnum = n;
}
~teacher(){
cout << "destroying teacher" << endl;
}
};
class student: public teacher{
private:
int Snum;
public:
student(){
Snum =0;
}
student(int n){
cout << " creating student"<<endl;
Snum = n;
}
~student(){
cout << "destroying student"<<endl;
teacher t(1);
cout << "teacher created"<<endl;
}
};
int main(){
teacher t(20);
student s(30);
}
You showed an example that compiles. What happens?
It behaves just like an object created in any other function, and it will be destroyed once it goes out of scope.
From 12.4p8 we find that:
After executing the body of the destructor and destroying any automatic objects allocated within the body [...]
This confirms that creating objects in the body of the destructor is legal.
But, be careful! It could hurt you if the constructors of those objects throw exceptions, because destructors are non-throwing and encountering an exception would result in the termination of the application.
When I override copy constructor why it segfaults in first delete itself.
output:
$./a.out
inside ctor
inside copy-ctor
Say i am in someFunc
inside dtor
*** glibc detected *** ./a.out: free(): invalid pointer: 0xb75f3000 ***
if I do not override copy-ctor then I could see that s1.PrintVal() is getting called and then there is seg fault in *ptr that is expected.
Why there is two different behavior with and without default and overridden copy-ctor?
#include<iostream>
using namespace std;
class Sample
{
public:
int *ptr;
Sample(int i)
{
cout << "inside ctor" << endl;
ptr = new int(i);
}
Sample(const Sample &rhs)
{
cout << "inside copy-ctor" << endl;
}
~Sample()
{
cout << "inside dtor" << endl;
delete ptr;
}
void PrintVal()
{
cout <<" inside PrintVal()."<<endl;
cout << "The value is " << *ptr<<endl;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
return 0;
}
In your copy-ctor, you don't actually copy ptr, meaning its value will be unspecified, and you'll be deleting an unspecified pointer (instead of double-deleting a normal pointer as you do with the defauly copy-ctor).
The default copy ctor copies every member by value. This will create an alias to the pointer so each class when its dtor is called will delete the pointer and cause a fault.
In almost any class where you have a pointer that is being allocate you will need to write a custom copy constructor to allocate the pointer and then copy the value.
class Sample
{
public:
int *ptr;
Sample(int i)
{
cout << "inside ctor" << endl;
ptr = new int(i);
}
Sample(const Sample &rhs)
{
ptr = new int(*rhs.ptr);
}
Sample & operator=(const Sample& other)
{
// You should also override copy assignment if you overide copy
// you don't need to allocate in this case just copy the value
*ptr = *other.ptr;
}
~Sample()
{
cout << "inside dtor" << endl;
delete ptr;
}
void PrintVal()
{
cout <<" inside PrintVal()."<<endl;
cout << "The value is " << *ptr<<endl;
}
};
You should look up the rule of three and if your in c++ 11 the rule of five