two different behavior in using default and overridden copy constructor - c++

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

Related

C++: What is the order of destructor call with methods?

I got this code:
Edit: The full code:
#include <iostream>
using namespace std;
class A {
public:
A() {}
A(const A& a) {
cout << "A copy ctor" << endl;
}
virtual ~A() {
cout << "A dtor" << endl;
}
virtual void type() const {
cout << "This is A" << endl;
}
};
class B: public A {
public:
B(){}
virtual ~B() {
cout << "B dtor" << endl;
}
void type() const override {
cout << "This is B" << endl;
}
};
A f(A a) {
a.type();
return a;
}
const A& g(const A& a) {
a.type();
return a;
}
int main() {
A* pa = new B();
cout << "applying function f:" << endl;
f(*pa).type();
cout << "applying function g:" << endl;
g(*pa).type();
delete pa;
return 0;
}
I noticed when debugging the code that after making and passing a copy of *pa to f and ending the function the destructor of the copy (*pa) that was passed to f is not called.
Only when type() ended (the same line) both the copies (I assume) were erased by the destructors
I was sure that when ending the function a destructor will be called and erase the current copy which did not happened in this case. I would like to get an explanation to the order in which the constructors and desturctors are being called in the code (I am not very knowledgeable about the order when methods are involved and I could not find much about it online).
thank you.
When you do f(*pa).type();, the Copy Constructor of A is called with an A object, so it will create an A to pass into your f function. When f returns, it is a different A being returned, since it's not by ref, however, it is NOT immediately destroyed, and instead uses copy-elision to stick around until after the .type() is called.
After that point, the destructor of both the temporary object passed into f, and the temporary object return by f are destroyed, so ~A() gets called twice.

Empty user-defined move constructor

The following code snippet which I was writing to understand move CTOR behaviour is giving me hard time to understand it's output:
#include <iostream>
class Temp
{
public:
Temp(){
std::cout << "Temp DEFAULT CTOR called" << std::endl;
mp_Val = nullptr;
}
Temp(int inp) {
std::cout << "Temp CTOR called" << std::endl;
mp_Val = new int(inp);
}
Temp(const Temp& inp) {
std::cout << "Temp COPY CTOR called" << std::endl;
mp_Val = new int(*inp.mp_Val);
}
Temp& operator= (const Temp& inp) {
std::cout << "Temp ASSIGNMENT OPER called" << std::endl;
mp_Val = new int(*inp.mp_Val);
return *this;
}
int* mp_Val;
};
class B
{
public:
B(){
std::cout << "Class B DEFAULT CTOR" << std::endl;
mp_Val = nullptr;
}
B(int inp) {
std::cout << "Class B CTOR" << std::endl;
mp_Val = new Temp(inp);
}
B(const B& in) {
std::cout << "Class B COPY CTOR" << std::endl;
mp_Val = in.mp_Val;
}
B(B&& in){
std::cout << "Class B MOVE CTOR" << std::endl; //Doubt: 1
}
Temp *mp_Val;
};
int main() {
B obj1(200);
B obj2 = std::move(obj1);
auto temp = obj1.mp_Val;
std::cout << "Obj1 B::Temp address: " << obj1.mp_Val << std::endl;
std::cout << "Obj2 B::Temp address: " << obj2.mp_Val << std::endl; //Doubt: 2
return 0;
}
Output:
Class B CTOR
Temp CTOR called
Class B MOVE CTOR
Obj1 B::Temp address: 0xd48030
Obj2 B::Temp address: 0x400880
GCC version: 4.6.3
My question is about the line marked as Doubt 2. Should not the address be printed as 0? As per my understanding, as I have defined an empty move CTOR (marked as Doubt 1) in class B, it should call the default CTOR of class Temp (which it's not calling as evident from the logs) to initialise its member variable mp_Val of type Temp.
There is obviously something that I am missing.
As per my understanding, as I have defined an empty move CTOR (marked as Doubt 1) in class B, it should call the default CTOR of class Temp (which it's not calling as evident from the logs) to initialise its member variable mp_Val of type Temp.
Your member variable isn't of type Temp, it's of type Temp *. You're right that the lack of an initialiser means that that member will be default-constructed, and for type Temp that would involve calling the default constructor. However, for pointer types, default construction leaves the object uninitialised.

why copy constructor is getting called even though I am actually copying to already created object in C++?

I wrote below code and I didn't understand why copy constructor is getting called.
#include <iostream>
using namespace std;
class abc
{
public:
abc()
{
cout << "in Construcutor" << (this) << endl;
};
~abc()
{
cout << "in Destrucutor" << (this) << endl;
};
abc(const abc &obj)
{
cout << "in copy constructor" << (this) << endl;
cout << "in copy constructor src " << &obj << endl;
}
abc& operator=(const abc &obj)
{
cout << "in operator =" << (this) << endl;
cout << "in operator = src " << &obj << endl;
}
};
abc myfunc()
{
static abc tmp;
return tmp;
}
int main()
{
abc obj1;
obj1 = myfunc();
cout << "OK. I got here" << endl;
}
when I ran this program, I am getting the following output
in Construcutor0xbff0e6fe
in Construcutor0x804a100
in copy constructor0xbff0e6ff
in copy constructor src 0x804a100
in operator =0xbff0e6fe
in operator = src 0xbff0e6ff
in Destrucutor0xbff0e6ff
OK. I got here
in Destrucutor0xbff0e6fe
in Destrucutor0x804a100
I didn't understand why copy constructor is getting called when I was actually assigning the object.
If I declare abc tmp, instead of static abc tmp in myfunc(), then copy constructor is not getting called. Can any one please help me to understand what is going on here.
Because you return an object by value from myfunc, which means it's getting copied.
The reason the copy-constructor is not getting called if you don't make the object static in myfunc is because of copy elision and return value optimization (a.k.a. RVO). Note that even though your copy-constructor may not be called, it still has to exist.

C++ singleton with private constructor

I need singleton with a application lifetime, guaranteed creation/destruction and static access to it.
#include <iostream>
#include <cstdlib>
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#define M() C::sM()
#define M2() C::sM2()
using namespace std;
class C {
private:
static C* s;
~C() { cout << "~C()" << endl; }
static C* instance() {
if (s==NULL) { s=new C(); }
cout << "instance()=" << s << endl; return s;
}
static void cleanUp() { delete s; }
void m() { cout << "m()" << endl; }
void m2() { cout << "m2()" << endl; }
DISALLOW_COPY_AND_ASSIGN(C);
public:
C() {
cout << "C()" << endl; if (s==NULL) {
s=this; atexit(&cleanUp);
cout << "cleanUp is installed" << endl;
} else {
cout << "cleanUp is not installed" << endl;
}
}
void* operator new(size_t sz) {
void* p=NULL; if (s==NULL) { p=new char[sz]; } else { p=s; }
cout << "new(" << sz << ")=" << p << endl;
return p;
}
void operator delete(void* p, size_t sz) {
cout << "delete(" << sz << "," << p << ")" << endl;
if (p) delete[] static_cast<char*>(p); s=NULL;
}
void static sM() { cout << "sM()" << endl; instance()->m(); }
void static sM2() { cout << "sM2()" << endl; instance()->m2(); }
};
C* C::s = NULL;
int main() {
M();
M2();
C* p1 = new C();
C* p2 = new C();
}
But I don't know how to get rid of g++ warning:
test.cpp: In static member function 'static void C::operator delete(void*, size_t)':
test.cpp:22: warning: deleting 'void*' is undefined
If I write C* instead of void*, destructor start calling itself in infinite loop. Can anybody help me to get clean code without warnings? C++98 of course.
The way I'm used to write singletons (whenever I really need one) is:
class Singleton
{
public:
static Singleton& instance()
{
static Singleton theInstance;
return theInstance;
}
private:
Singleton()
{
}
};
No need to mess around with overloading new and delete.
You do not need to overload neither new() nor delete().
And you probably do not need to hand out a pointer to your customers. A reference will do.
Construction and destruction of the singleton will be done in your instance(), which could look like so:
static C& instance() {
static C _instance;
cout << "instance()" << endl;
return _instance;
}
This guarantees construction and destruction, because the constructor of C is called when the first user calls instance(), and only with the first call.
Destruction will happen at the end of your program.
The type to delete is char*:
void operator delete(void* p, size_t sz) {
cout << "delete(" << sz << "," << p << ")" << endl;
if (p) delete (char*) p;
}
There is a bug in your new: What's the difference between new char[10] and new char(10)
Maybe should be:
p=new char[sz];
and then
delete[] (char*)p ;
---- edited:
The delete for purists, sacrificing clarity to people learning ;P :
delete[] static_cast<char*>(p) ;
(*actually I appreciate the note about the cast)
It looks to me like your code should work if you just remove the new and delete overloads (which I don't really see the point of, if you want to log every con/destruction, do so in the con/destructors), but the below should fix your error.
Since you assign a char* to p, casting it to char* in the delete should work, i.e. delete (char*)p;.
However, I believe p=new char(sz); is making a char with a value of sz instead of a char array of size sz. For the latter, you may want p=new char[sz]; and then delete[] p or delete[] (char*)p;.

Returning pointer by value does not move the object

I have compiled this code with vs2011. It prints first constructor then copy constructor.
But if I change the function to return a instead of ap, it will move the object. Is this a bug or why does it behave like this? Is *ap not a rvalue?
struct A
{
A() { cout << "constructor" << endl;}
A(const A&) { cout << "copy constructor " << endl;}
void operator=(const A&) { cout << "assignment operator" << endl; }
A( A&&) { cout << "move copy constructor" << endl;}
void operator=(A&&) { cout << "move assignment operator" << endl;}
};
A func() { A a; A *ap = &a; return *ap; }
int main()
{
A a = func();
return 0;
}
*ap is an lvalue (ยง 5.3.1.1, n3290) which is in general not safe for the move to happen automatically. The local variable return a; is a different case. There's no requirement for the compiler to prove that in this specific instance it would be safe. This is another good reason for not using pointers in cases where you don't really want pointer semantics.
Changing it to:
return std::move(*ap);
will cause it to be explicitly moved however.