vector and push_back() - c++

#include <iostream>
#include <vector>
#include <algorithm>
class my {
public:
my() {
counter++;
std::cout << "class constructor" << counter << " \n";}
~my() {
std::cout << "class destructor" << counter << " \n";
counter--;
}
static inline int counter = 0;
};
int main()
{
my v1;
std::vector<my> my_vec;
my * p = new my();
my_vec.push_back(std::move(*p));
my_vec.push_back(std::move(v1));
}
simply example, however I do not understand what I am doing wrong, in result I get 2 extra destructor called than I expect (expect 2). Could some one explain it?
results:
class constructor1
class constructor2
class destructor2
class destructor1
class destructor0
class destructor-1

Analyzing the program step-by-step:
my v1;
One Instance is created, constructor is called.
my * p = new my();
Another instance is created, constructor is called.
my_vec.push_back(std::move(*p));
A copy of the second instance is inserted into the vector; the implicitly defined move-constructor is called (which just copies; no output is printed).
my_vec.push_back(std::move(v1));
The vector allocates new storage for 2 instances, copies the previously stored instance into the new storage (invoking the implicitly defined move-constructor, which just does copying, still no output for this), and invokes the destructor for the instance in the old storage (so first destructor output is printed).
Then, the vector goes out of scope, so its two contained elements get destroyed (so, 2 destructor calls). Then, v1 goes out of scope, printing the 4th destructor call. The instance p is leaked, i.e. never destroyed (memory leak).

Please see inline ...
#include <iostream>
#include <vector>
class my {
public:
my() {
counter++;
std::cout << "class constructor" << counter << " \n";
std::cout << "Object Address : " << this << std::endl;
}
~my() {
std::cout << "class destructor" << counter << " \n";
std::cout << "Object Address : " << this << std::endl;
counter--;
}
static inline int counter = 0;
};
int main()
{
my v1; /* 1. Object on stack (constructor called) */
std::vector<my> my_vec;
my * p = new my(); /* 2. Object created on heap (constructor called) */
my_vec.push_back(std::move(*p));
my_vec.push_back(std::move(v1));
}
Output is:
class constructor 1 Address : 0x7ffee1488760
class constructor 2 Address : 0x7f9f47400350
class destructor 2 Address : 0x7f9f474026e0
class destructor 1 Address : 0x7f9f474026f1
class destructor 0 Address : 0x7f9f474026f0
class destructor -1 Address : 0x7ffee1488760
Object on the stack called destructor as soon as it goes out of the scope i.e. Scope of the object on stack is limited to the code block. In this case block end when main exits.
But the object on heap (new) is a potential leak, had this being inside while loop would have consumed memory and eventually crashed. For each new you need to explicitly called delete, which means you have to call its destructor. Thanks to stack it does that for us but not heap, and c++ also doesn't have garbage collector.
std::move is a copy operation and hence no constructor is called. details here.

Related

Scope of an object created in a function

I have created an object of a class inside a function. The created object is passed as a parameter to another class. I expect that when I exit the function in which the object is created, the object must be destroyed.
Also any references to this object must be invalid, but I find that the object referenced after exiting the function is still valid. Trying to understand the scope of the object. The code snipped is given below.
class TextWidget
{
public:
TextWidget()
{
cout << "Constructor TextWidget" << endl;
}
TextWidget(int id)
{
_ID = id;
cout << "Constructor TextWidget" << endl;
}
~TextWidget()
{
cout << "Destructor TextWidget" << endl;
}
void printWidgetInstance()
{
cout << this << endl;
}
int _ID;
};
class AnotherWidget
{
public:
AnotherWidget()
{
cout << "Constructor AnotherWidget" << endl;
}
~AnotherWidget()
{
cout << "Destructor AnotherWidget" << endl;
}
TextWidget* getTextWidget()
{
return _textWidget;
}
void setTextWidget(TextWidget* t)
{
_textWidget = t;
}
int getTextID() { return _textWidget->_ID; }
private:
TextWidget* _textWidget;
};
ButtonWidget b;
AnotherWidget a;
void fun()
{
TextWidget t(7);
b.setTextWidget(&t);
a.setTextWidget(&t);
a.getTextWidget()->printWidgetInstance();
b.getTextWidget()->printWidgetInstance();
}
int main()
{
fun();
cout << "TextWidget in AnotherWidget is ";
a.getTextWidget()->printWidgetInstance();
cout << "Text ID in a is " << a.getTextID() << endl;
getchar();
return 0;
}
OUTPUT
Constructor AnotherWidget
Constructor TextWidget
Before deleting TextWidget in class ButtonWidget 0x73fdf0
Before deleting TextWidget in class AnotherWidget 0x73fdf0
0x73fdf0
0x73fdf0
Destructor TextWidget
TextWidget in AnotherWidget is 0x73fdf0
Text ID in a is 7
A variable declared using automatic storage duration (not using new) has a lifetime of its scope. Accessing the variable outside the scope results in undefined behavior.
You need to understand what classes, objects, pointers and references are. Classes are code in memory, this code deals with the member variables. A class does not occupy any data memory. When you create a object you instantiate the class. This step will reserve some data memory for the local data of one object instance of the class. To access this instance you get a reference to the object (this). An object variable holds a pointer to the data memory of an instance of a class.
When an object gets destroyed the occupied memory block gets listed as free but not cleared. So if you still have a reference to that memory block you may access it. And as long as the system doesnt use this memory block for other purposes you still will find your bits and bytes there.
You may declare some variables:
long long_array[10];
myclass myobject;
These variables are stored sequential in one memory block. When you now access the memory behind the long_array through that array:
long_array[10] = 12345; // valid range is from long_array[0] to long_array[9]
Than you will overwrite the data of the object myobject.

Is the previous object destroyed when the variable holding it gets assigned a new one using a copy constructor?

Take a look at this code:
#include <iostream>
using namespace std;
class A {
private:
int _x;
int _id;
static int count;
public:
A(int x) : _x(x) {
this->_id = A::count++;
cout << "Object with id " << this->_id
<< " has been created." << endl;
}
~A() {
cout << "Object with id " << this->_id
<< " has been destroyed." << endl;
}
int get_x(void) {
return this->_x;
}
A add(A& object) {
A tmp(this->_x + object._x);
return tmp;
}
};
int A::count = 1;
int main(void) {
A object_1(13);
A object_2(5);
A object_3(12);
object_3 = object_1.add(object_2);
cout << object_3.get_x() << endl;
return 0;
}
Here's the output from the program:
Object with id 1 has been created.
Object with id 2 has been created.
Object with id 3 has been created.
Object with id 4 has been created.
Object with id 4 has been destroyed.
18
Object with id 4 has been destroyed.
Object with id 2 has been destroyed.
Object with id 1 has been destroyed.
I don't understand what happened to Object with id 3? It definitely was created, but I see no line telling me that it was ever destroyed. Can you please tell me what's going on here?
As an aside question, why is it that when I use return 0, the destructors work fine, but when I use exit(EXIT_SUCCESS) I don't see Object with # has been destroyed printed on the screen as though the destructors are never called.
Is the previous object destroyed when the variable holding it gets assigned a new one using a copy constructor?
This question is moot because it is not possible to do so.
When you run
object_a = object_b;
this calls the assignment operator (not the copy constructor). It does not create or destroy any objects (unless your assignment operator does that).
In this case you haven't defined an assignment operator, so the default one is used, which overwrites object_3's ID with the other object's ID (which is 4). So when object_3 is destroyed it prints "Object with id 4 has been destroyed".

What is the logic behind these destructor calls

I ran the following code
#include <iostream>
using namespace std;
class Count
{
private:
int count;
public:
//Constructor
Count():count(0) { cout << "Constructor called" << endl; }
//Destructor
~Count() { cout << "Destructor called" << endl; }
//Display the value.
Count display()
{
cout << "The value of count is " << count << endl;
return *this;
}
};
int main()
{
Count C;
C.display();
}
Result :-
Constructor called
The value of count is 0
Destructor called
Destructor called
In the above case, the destructor is called twice, one for destruction of the "this" object and one for return from main.
Is my observation correct ??
Can anyone explain me also the temporary object created in this process like why it is created, if created??
You are returning a copy from display() method thus it needs to be destructed too. So, in your main you actually have 2 objects, one - implicitly.
The destructor is called twice because your display function returns a copy of the Count instance that it is called on. So that gets destroyed along with your C instance within main.
2 instances = 2 destructor calls.
If you specify and implement your function to return an instance of Count then it will do so. If you don't want this behaviour, then change the return type to void and don't return anything - then your code will contain just the one instance C.
Your code here
Count display() {
// ^^^^^
cout << "The value of count is " << count << endl;
return *this; // <<<<<<
}
creates an implicit copy of your instance that is returned and immediately destroyed, hence the second destructor call.
Yes correct.
Your function display() created a copy which made a second object.
if you return a reference you wouldn't get the copy.
Count& display() { return *this; }

make_shared() calling destructor twice when giving it an already created object

Using VS 2015 with v120.
So I am getting memory exceptions because when I call make_shared() on an already constructed object. The already constructed object has a pointer to another object that was allocated with new so when it calls the destructor the first time. The object is destroyed, then when it calls it again, the object is already destroyed.
I thought that in this instance the object will be moved and the destructor is never called.
Code:
Sub-object:
#include "Obj.h"
Obj::Obj(int i)
{
cout << "const Obj " << this << "\n";
m_i = i;
}
Obj::~Obj()
{
cout << "-------------------DELETING o " << this << "\n";
}
Containing Object:
#include "BigObj.h"
BigObj::BigObj(int i)
{
cout << "const BIgObj " << this << "\n";
m_o = new Obj(i);
}
BigObj::BigObj()
{
}
BigObj::BigObj(const BigObj& o)
{
cout << "called copy const \n";
m_o = o.m_o;
}
BigObj::~BigObj()
{
delete m_o;
cout << "----------------DEL bigobj " << this << "\n";
}
Main:
int main(char argc, char** argv){
BigObj oo = BigObj(10);
shared_ptr<BigObj> shr= make_shared<BigObj>(oo);
BigObj oo2 = BigObj(100);
cout << "finished\n";
system("pause");
}
Output:
const BIgObj 000000C61F4FFAD8
const Obj 000000C61F658330
called copy const
const BIgObj 000000C61F4FFB28
const Obj 000000C61F658510
finished
Press any key to continue . . .
-------------------DELETING o 000000C61F658510
----------------DEL bigobj 000000C61F4FFB28
-------------------DELETING o 000000C61F658330
----------------DEL bigobj 000000C61F65AFB0
-------------------DELETING o 000000C61F658330
This is test code I made to show the problem. In the real project I create objects that need to contain a lot of info and then they are pushed onto a vector that is made shared for various threads to work on the info. This so whatever thread has the object last deletes it.
Erm - you copy constructor (of BigObj) copies the internal pointer (Obj) and then then there are two deletes on it (once the automatic instance is cleaned up and then the shared pointer) This is not good.. Copy constructor (of BigObj) is not doing the right thing, it should instantiate the subobject (Obj) using it's (of Obj) copy constructor...
EDIT: A clean-ish implementation..
class Obj
{
};
class BigObj
{
public:
// Default constructor
BigObj() : _obj(new Obj)
{ }
// Move constructor
BigObj(BigObj&& other) : _obj(move(other._obj)) // take ownership of the subobject
{ }
// Move assignment
BigObj& operator=(BigObj&& other)
{
_obj = move(other._obj); // take ownership of the subobject
return *this;
}
private:
unique_ptr<Obj> _obj;
};
This:
BigObj oo = BigObj(10);
shared_ptr<BigObj> shr= make_shared<BigObj>(oo);
Isn't doing what you think it is. You are creating a shared pointer and putting a copy of oo into it. Your copy constructor is copying m_o. This now means in your main you have TWO BigObj objects: oo and the newly made copy held by shr
Since both of their m_o members point at the same memory, their destructors will call delete on m_o twice.
You don't need oo first, you may construct the object in place using make_shared:
shared_ptr<BigObj> shr = make_shared<BigObj>(10);
This should fix your problem, but you should also look into deep versus shallow copies for why the copy constructor is problematic.

returning C++ stack variable

In this example, why is it ok to return a stack variable? When t() returns, why is it not returning garbage, since the stack pointer has been incremented?
#include << string >>
#include << vector >>
#include << iostream >>
using namespace std;
class X{
public:
X() { cout << "constructor" << endl; }
~X() { cout << "destructor" << endl; }
};
vector <X> t()
{
cout << "t() start" << endl;
vector<X> my_x;
int i = 0;
printf("t: %x %x %x\n", t, &my_x, &i);
my\_x.push\_back(X()); my\_x.push\_back(X()); my\_x.push\_back(X());
cout << "t() done" << endl;
return my_x;
}
int main()
{
cout << "main start" << endl;
vector <X> g = t();
printf("main: %x\n", &g);
return 0;
}
output:
./a.out
main start
t() start
t: 8048984 bfeb66d0 bfeb667c
constructor
destructor
constructor
destructor
destructor
constructor
destructor
destructor
destructor
t() done
main: bfeb66d0
destructor
destructor
destructor
Basically when you return the stack variable my_x you would be calling the copy constructor to create a new copy of the variable. This is not true, in this case, thanks to the all mighty compiler.
The compiler uses a trick known as return by value optimization by making the variable my_x really being constructed in the place of memory assigned for g on the main method. This is why you see the same address bfeb66d0 being printed. This avoids memory allocation and copy construction.
Sometimes this is not at all possible due to the complexity of the code and then the compiler resets to the default behavior, creating a copy of the object.
Because parameters are passed by value. A copy is made. So what is being returned is not the value on the stack, but a copy of it.
Well a copy is returned, the only construct you can not return a copy of it is a static array. So you can not say this...
int[] retArray()
{
int arr[101];
return arr;
}
The compiler is optimized to handle returning "stack variables" without calling the copy constructor. The only thing you need to know about is that that memory allocation is in scope of both the function that allocated it on the stack and the function that the object is returned to.
It does NOT call the copy constructor nor does it allocate it twice.
There may be some special cases and of course it depends on the compiler -- for example, primitives may be copied -- but in general, objects allocated on the stack, don't get copied when being returned.
Example:
struct Test {
};
Test getTest() {
Test t;
std::cout << &t << std::endl; // 0xbfeea75f
return t;
}
int main(int argc, char *argv[])
{
Test t = getTest();
std::cout << &t << std::endl; // also 0xbfeea75f
}