Confusion about construction/destruction in vector after std::vector::clear - c++

#include <iostream>
#include <vector>
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
};
int main()
{
std::vector<A> myvec;
myvec.push_back(A());
myvec.push_back(A());
myvec.clear();
return 0;
}
output:
constructor
destructor
constructor
destructor
destructor
destructor
destructor
There are five calls to the destructor here. The first two are due to the temporaries which are passed to push_back. There are three other calls, but I expected one two extra calls.
myvec.clear() will clear only two contents so destructor of A should call only two times (instead of three). why there is one extra time destructor is called?
But, if I push_back only one element to the vector, instead of two, the output is as I expected.

The call to std::vector::clear isn't really important in this context because, when myvec goes out of scope, its contents will be destroyed anyway.
Let's consider
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
A (const A &) { std::cout << "A(A&)\n"; }
};
int main()
{
std::vector<A> myvec;
std::cout << "First\n";
myvec.push_back(A());
std::cout << "Second\n";
myvec.push_back(A());
std::cout << '\n'; // to separate the final destruction
myvec.clear();
}
which outputs
First
constructor <-- First A _temporary_ object created when pushing_back
A(A&) <-- vector makes a *copy* of the temporary
destructor <-- Temporary A is destroyed
Second
constructor <-- Second A _temporary_ object created when pushing_back
A(A&) <-- Reallocation happens: vector can't copy because it ran out of space
A(A&) <-- Copy of the second temporary
destructor <-- Destroy of the temporary
destructor <-- Destroy of the first element
destructor
destructor
If you std::vector::reserve some space, you can get rid of the copies made by the reallocation
std::vector<A> myvec;
myvec.reserve(8);
which confirms what said
First
constructor
A(A&)
destructor
Second
constructor
A(A&)
destructor
push_back is still making copies of the parameter: this can be further optimized by making your class moveable.
A(A&&) noexcept = default;
A& operator=(A&&) noexcept = default;
First
constructor
destructor
Second
constructor
destructor

This is most likely due to the reallocation that takes place between the first and the second push_back. If you reserve some space ahead of time, then the deallocations are going to be 2 after the two push_backs, as you have expected.

Try this slightly modified version of your program. There is now a copy constructor and an optional reserve (see comment in the program). It will be a lot clearer what is going on.
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A() { cout << " constructor" << endl; }
A(const A & a) { cout << " copy constructor" << endl; }
~A() { cout << " destructor" << endl; }
};
int main()
{
vector<A> myvec;
// myvec.reserve(100); // <<< remove comment to see the difference
cout << "pushback 1" << endl;
myvec.push_back(A());
cout << "pushback 2" << endl;
myvec.push_back(A());
cout << "pushback 3" << endl;
myvec.push_back(A());
cout << "clear" << endl;
myvec.clear();
cout << "end clear" << endl;
return 0;
}

Related

Does creating an object directly in a vector, and then removing it from the vector, calls to a destructor?

Say i have a class named test, and a vector
std::vector<test> Tests;
If i execute this code:
Tests.push_back(test());
and then
Tests.pop_back();
What happens to the test object? Is its destructor being called upon?
This example might show a little bit better what happens.
Live demo here : https://onlinegdb.com/c6-N-vyPc
Output will be :
Creating first vector (push_back)
>>>> Test constructor called
>>>> Test move constructor called
<<<< Test destructor called
Destroying first vector
<<<< Test destructor called
Creating second vector (emplace_back)
>>>> Test constructor called
Destroying second vector
<<<< Test destructor called
Example code :
#include <iostream>
#include <vector>
class Test
{
public:
Test()
{
std::cout << ">>>> Test constructor called\n";
}
Test(const Test&)
{
std::cout << ">>>> Test copy constructor called\n";
}
Test(Test&&)
{
std::cout << ">>>> Test move constructor called\n";
}
~Test()
{
std::cout << "<<<< Test destructor called\n";
}
};
int main()
{
// scope to manage life cycle of vec1
{
std::cout << "\nCreating first vector (push_back)\n";
std::vector<Test> vec1;
vec1.push_back(Test{});
std::cout << "Destroying first vector\n";
}
// scope to manage life cycle of vec2
{
std::cout << "\nCreating second vector (emplace_back)\n";
std::vector<Test> vec2;
vec2.emplace_back();
std::cout << "Destroying second vector\n";
}
return 0;
}

vector elements allocated on stack?

#include <iostream>
#include <vector>
using namespace std;
struct A {
int i = 0;
};
void append(vector<A>& v) {
auto a = v.back(); // is a allocated on the stack? Will it be cleaned after append() returns?
++a.i;
v.push_back(a);
}
void run() {
vector<A> v{};
v.push_back(A{}); // is A{} created on the stack? Will it be cleaned after run() returns?
append(v);
for (auto& a : v) {
cout << a.i << endl;
}
}
int main() {
run();
return 0;
}
The code above prints as expected:
0
1
But I have two questions:
is A{} created on the stack? Will it be cleaned after run() returns?
is a allocated on the stack? Will it be cleaned after append() returns?
Update:
#include <iostream>
#include <vector>
using namespace std;
struct A {
int i = 0;
A() { cout << "+++Constructor invoked." << endl; }
A(const A& a) { cout << "Copy constructor invoked." << endl; }
A& operator=(const A& a) {
cout << "Copy assignment operator invoked." << endl;
return *this;
};
A(A&& a) { cout << "Move constructor invoked." << endl; }
A& operator=(A&& a) {
cout << "Move assignment operator invoked." << endl;
return *this;
}
~A() { cout << "---Destructor invoked." << endl; }
};
void append(vector<A>& v) {
cout << "before v.back()" << endl;
auto a = v.back();
++a.i;
cout << "before v.push_back()" << endl;
v.push_back(a);
cout << "after v.push_back()" << endl;
}
void run() {
vector<A> v{};
v.push_back(A{});
cout << "entering append" << endl;
append(v);
cout << "exited append" << endl;
for (auto& a : v) {
cout << a.i << endl;
}
}
int main() {
run();
return 0;
}
Output:
+++Constructor invoked.
Move constructor invoked.
---Destructor invoked.
entering append
before v.back()
Copy constructor invoked.
before v.push_back()
Copy constructor invoked.
Copy constructor invoked.
---Destructor invoked.
after v.push_back()
---Destructor invoked.
exited append
0
0 // I understand why it outputs 0 here. I omitted the actual work in my copy/move constructors overloads.
---Destructor invoked.
---Destructor invoked.
I updated the code in my question, adding the copy/move constructors. I found copy constructor was called 3 times in append. I understand auto a = v.back(); needs a copy, But the two other copies maybe should be avoided?
The C++ specification doesn't actually say.
With v.push_back(A{}) the A{} part creates a temporary object, which is then moved or copied into the vector, and then the temporary object is discarded.
Same with local variables, really, the "stack" is actually never mentioned by the C++ standard, it only tells how life-time should be handled. That a compiler might use a "stack" is an implementation detail.
With that said, most C++ compilers will use the "stack" to store local variables. Like for example the variable a in the append function. As for the temporary object created for v.push_back(A{}) you need to check the generated assembly code.
For the life-times, the life-time of the temporary object A{} ends as soon as the push_back function returns. And the life-time of a in the append function ends when the append function returns.
In this function
void append(vector<A>& v) {
auto a = v.back(); // is a allocated on the stack? Will it be cleaned after append() returns?
++a.i;
v.push_back(a);
}
the variable a has the automatic storage duration and is a local variable of the function. It will not be alive after exiting the function.
In this function
void run() {
vector<A> v{};
v.push_back(A{}); // is A{} created on the stack? Will it be cleaned after run() returns?
append(v);
for (auto& a : v) {
cout << a.i << endl;
}
}
again the variable v has the automatic storage duration and is a local variable of the function. When the function will finish its execution the variable will be destroyed. And all elements of the vector (that are placed in the heap) also will be destroyed due to the destructor of the vector.
Consider the following demonstrative program.
#include <iostream>
#include <vector>
struct A {
int i = 0;
};
int main()
{
std::vector<A> v;
std::cout << "&v = " << &v << "\n\n";
A a;
std::cout << "&a = " << &a << "\n\n";
v.push_back( a );
std::cout << "&v = " << &v << '\n';
std::cout << "&a = " << &a << '\n';
std::cout << "&v[0] = " << &v[0] << "\n\n";
++a.i;
v.push_back( a );
std::cout << "&v = " << &v << '\n';
std::cout << "&a = " << &a << '\n';
std::cout << "&v[0] = " << &v[0] << '\n';
std::cout << "&v[1] = " << &v[1] << "\n\n";
return 0;
}
Its output might look like
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v[0] = 0x55725232ee80
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v[0] = 0x55725232eea0
&v[1] = 0x55725232eea4
As you can see the addresses of the vector v and the object a looks similarly because they are allocated in the same outer block scope of the function and have the automatic storage duration.
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
And they are not changed when new values are pushed on the vector.
However the addresses of the elements of the vector as for example
&v[0] = 0x55725232ee80
&v[0] = 0x55725232eea0
&v[1] = 0x55725232eea4
have a different representation and can be changed when a new elements are added to the vector because the memory for them can be dynamically reallocated.
EDIT: After you updated your question then take into account that when a new element is added to the vector the elements of the vector can be reallocated calling the copy constructor. You can use the method reserve to reserve enough memory to avoid its reallocation and the method emplace_back.
is a allocated on the stack?
There is no such thing as "stack" storage in the language. a has automatic storage.
As far as language implementations are concerned, this typically means that the variable is probably stored in a register, or on stack, or nowhere.
Will it be cleaned after append() returns?
Yes. Automatic variables are destroyed automatically when they go out of scope.
is A{} created on the stack?
A{} is a temporary object. The language is a bit vague about the storage class of temporary objects, but it is clear about the lifetime.
Will it be cleaned after run() returns?
In this case, the temporary object is destroyed at the end of the full expression, which is before run returns.
vector elements allocated on stack?
No. Vector elements are created in dynamic storage.
Update
But the two other copies maybe should be avoided?
If your endgoal is to get a vector with two elements, you can avoid all of the copies like this:
std::vector<A> v(2);

Why constructor is not called when passed by value

I am reading up on copy constructors and the way they typically receive the parameters as constant references.
Why should the copy constructor accept its parameter by reference in C++?
I wrote a code snippet to test that when a parameter is received by value, whether a copy is created( as stated in the accepted answer of the provided link).
But I don't see the constructor called when an object is received by value.
Please explain why? And isn't a copy created when an object is returned by value too? again no constructor called there as well. Why?
class Vector
{
public:
Vector(){cout << "Vector constructor"<<endl;}
~Vector(){cout << "Vector destructor"<<endl;}
};
Vector use(Vector z)
{
cout << "At call" << endl;
Vector v;
cout << "after definition" << endl;
return v;
}
int main()
{
Vector t;
cout << "After irrelevant" << endl;
use(t);
cout << "After use"<< endl;
}
The output looks as follows:
Vector constructor
After irrelevant
At call
Vector constructor
after definition
Vector destructor
Vector destructor
After use
Vector destructor
Update1: I had missed adding the copy constructor in the initial example. Once that is done the code behaves as expected.
The default constructor is not called when an object is passed by value, the copy (or move) constructor is.
If we trace the copy constructor like this:
class Vector
{
public:
Vector(){cout << "Vector constructor"<<endl;}
Vector(const Vector&) {cout << "Vector copy constructor"<<endl;}
~Vector(){cout << "Vector destructor"<<endl;}
};
Then we see the constructor being called:
Vector constructor
After irrelevant
Vector copy constructor //here
At call
Vector constructor
after definition
Vector destructor
Vector destructor
After use
Vector destructor
There is no copy on the return because the copy is elided by the compiler for efficiency. If you pass -fno-elide-constructors or equivalent to your compiler then you'll see an additional copy.
Copy is created to pass the value, so copy constructor is called there.
#include <iostream>
using std::cout;
using std::endl;
class Vector
{
public:
Vector(){cout << "Vector constructor"<<endl;}
Vector(const Vector&){cout << "Vector copy constructor"<<endl;} // add this line
~Vector(){cout << "Vector destructor"<<endl;}
};
Vector use(Vector z)
{
cout << "At call" << endl;
Vector v;
cout << "after definition" << endl;
return v;
}
int main()
{
Vector t;
cout << "After irrelevant" << endl;
use(t);
cout << "After use"<< endl;
}
output:
Vector constructor
After irrelevant
Vector copy constructor
At call
Vector constructor
after definition
Vector destructor
Vector destructor
After use
Vector destructor

why c++ auto object optimization is happening in this code?

Why only one object of A is created in this program? and no copy constructor is called. What is this optimization called? If this is a valid/known optimization, will it not be a trouble for multiton design pattern?
#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
A () {
cout << "in-- Constructor A" << endl;
++as;
}
A (const A &a) {
cout << "in-- Copy-Constructor A" << endl;
++as;
}
~A() {
cout << "out --Constructor A" << endl;
--as;
}
A & operator=(const A &a) {
cout << "assignment" << endl;
++as;
//return *this;
}
static int as;
};
int A::as = 0;
A fxn() {
A a;
cout << "a: " << &a << endl;
return a;
}
int main() {
A b = fxn();
cout << "b: " << &b << endl;
cout << "did destructor of object a in func fxn called?" << endl;
return 0;
}
Output of above program
in-- Constructor A
a: 0x7fffeca3bed7
b: 0x7fffeca3bed7
did destructor of object a in func fxn called?
out --Constructor A
Go through link http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
It will help you.
This seems to be a case of a return value optimization. This optimization is notable in the C++ world as it is allowed to change the observable behavior of the program. It's one of the few, if not the only, optimization that's allowed to do that, and it's from the days where returning copies was considered a weakness. (With move semantics and generally faster machines, this is much, much less of an issue now.)
Basically, the compiler sees that it's going to copy the object, so instead it allocates room for it on the calling frame and then builds it there instead of calling the copy constructor.

Avoid multiple copying in vector in C++

My question is give below to avoid multiple copies in vector copying.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class DataValue {
public:
DataValue() { std::cout << "DataValue constructor called" << std::endl; }
DataValue(DataValue const& other) { cout << "DataValue copy constructor called" << std::endl; }
~DataValue() { std::cout << "DataValue destructor is called" << std::endl; }
private:
};
class ItemDataHistory {
public:
ItemDataHistory() { std::cout << "ItemDataHistory constructor called" << std::endl; }
// ItemDataHistory(ItemDataHistory const & other) { std::cout << "ItemDataHistory copy constructor called" << std::endl; }
~ItemDataHistory() { std::cout << "ItemDataHistory destructor called" << std::endl; }
std::vector<DataValue>& GetVecDataValues() { return m_vecDataValues; }
private:
std::vector<DataValue> m_vecDataValues;
};
class DataReply {
public:
DataReply() { std::cout << "Data reply constructor is called "<< std::endl; }
~DataReply() { std::cout << "Data reply destructor is called "<< std::endl; }
DataReply(const DataReply& ) { std::cout << "Data reply copy constructor is called "<< std::endl; }
std::vector<ItemDataHistory>& GetItemDataHistories() { return m_vecItemData; }
private:
// The list of DataValue
std::vector<ItemDataHistory> m_vecItemData;
};
void main()
{
DataValue dv1, dv2, dv3;
ItemDataHistory itmDH;
itmDH.GetVecDataValues().reserve(3);
itmDH.GetVecDataValues().push_back(dv1);
itmDH.GetVecDataValues().push_back(dv2);
itmDH.GetVecDataValues().push_back(dv3);
DataReply dr;
dr.GetItemDataHistories().reserve(1);
dr.GetItemDataHistories().push_back(itmDH); // Here copy consturtor of itemdatahistory is called and all data values are copied.
// Here I want to avoid data values constructor to be called again how can I avoid this
// How can I directly insert values of dv1, dv2, dv3 into "dr" with out using "itmDH"?
return;
}
Note here I cannot use pointer in above std::vector m_vecItemData; in data reply class as these are interface classes from libary and don't have control on it and I am calling function so function may use data while data in scope
My question is given in above comment in code. Reason is that I have thousands of data values. To avoid multiple constructors of data values to be called, I want to insert data values directly to data reply (i.e., with out using itmDH local variable)
and other questions is
How I can reserve space of data values inside data reply?
With C++11, you have two options:
make your type ItemDataHistory movable and move your data (if possible) with dr.GetItemDataHistories().push_back(std::move(itmDH));
look into new member function of containers, e.g. emplace_back().
In C++11, you can use move semantics.
Instead of doing this:
itmDH.GetVecDataValues().push_back(dv1);
itmDH.GetVecDataValues().push_back(dv2);
itmDH.GetVecDataValues().push_back(dv3);
You could do this:
itmDH.GetVecDataValues().push_back(std::move(dv1));
itmDH.GetVecDataValues().push_back(std::move(dv2));
itmDH.GetVecDataValues().push_back(std::move(dv3));
Instead of copying values, they are simply moved into the vector.
And instead of copying itmDH
dr.GetItemDataHistories().push_back(itmDH);
you could move it as well:
dr.GetItemDataHistories().push_back(std::move(itmDH));
In addition you also need move constructors. Here's an example:
DataValue(DataValue&& other){
std::cout << "DataValue move constructor called" << std::endl;
}
You may also declare and define move assignment operator:
DataValue& operator=(DataValue&& other){
std::cout << "DataValue move assigment operator is called" << std::endl;
return *this;
}
In order to fully understand move semantics (and rvalue references as well) please take a look at the following links:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
http://thbecker.net/articles/rvalue_references/section_01.html