Wednesday, September 25, 2019

c++ - emplace_back calls move constructor, and destructor



I try to emplace two instance of the class cBar to a vector with emplace_back function.



According to the reference calling an emplace_back only reserve the place in the vector, then create the new instance "in place".




Now, I tried to experiment with it:



#include 
#include
#include
#include


class cBar

{
public:

cBar(const int index);
cBar(cBar&& other); //needed for emplace_back?
~cBar();

private:
cBar(const cBar& other) = delete;
cBar& operator=(const cBar& other) = delete;


public:
int mIndex;

};




cBar::cBar(const int index) : mIndex(index)

{
std::cout << "cBar being created ..." << std::endl;
}
cBar::cBar(cBar&& other) : mIndex(other.mIndex)
{
std::cout << "cBar being moved ..." << std::endl;
}
cBar::~cBar()
{
std::cout << "cBar being destroyed ..." << std::endl;

}

int main()
{
std::vector mBars;

std::cout << "Begin to create 2 cBar instance, I am expecting 2 \"cBar being created ...\" messages here" << std::endl;
mBars.emplace_back(0);//this supposed to call only cBar(const int index) constructor, and nothing more
mBars.emplace_back(1);//this works as expected, only one constructor call


//destroy all
std::cout << "Destroy the 2 isntances (this works, I see the two expected \"cBar being destroyed ...\" messages here" << std::endl;
mBars.clear();

std::cin.get();
return 0;
}


Output:




Begin to create 2 cBar instance, I am expecting 2 "cBar being created ..." messages here
cBar being created ...
cBar being moved ...
cBar being destroyed ...
cBar being created ...
Destroy the 2 isntances (this works, I see the two expected "cBar being destroyed ..." messages here
cBar being destroyed ...
cBar being destroyed ...



If you run the one above, you will see that the first emplace_back creates the instance "in place", but then immediately call the move constructor, and then destructor is called.



What is more strange, that in case of the second emplace, I see the expected behavior: Only one constructor call.



I have two questions:




  1. Why do I need to define a move constructor in my class if I just want to emplace_back items, and never use push_back.


  2. In case of the first instance creation, why the move constructor, then the destructor is called? If I access the data of the first instance all seems to correct, so I have no idea why the move constructor, and destructor is called.





I use Visual Studio 2015.



Output with vector sizes in each step:



Begin to create 2 cBar instance, I am expecting 2 "cBar being created ..." messages here
Vector size:0
cBar being created ...
Vector size:1

cBar being moved ...
cBar being destroyed ...
cBar being created ...
Vector size:2
Destroy the 2 isntances (this works, I see the two expected "cBar being destroyed ..." messages here
cBar being destroyed ...
cBar being destroyed ...

Answer





2.In case of the first instance creation, why the move constructor, then the destructor is called?




Because the insertion of the 2nd element by emplace_back causes the reallocation; the inner storage of the vector needs to be extended, the elements in the old storage have to be copied/moved to the new storage, then destroyed.




1.Why do I need to define a move constructor in my class if I just want to emplace_back items, and never use push_back.




As the above explanation said, vector needs to move elements by copy/move operation. So you have to define the copy or move constructor for the class. This is true for both emplace_back and push_back, because they both add elements to vector and might cause reallocation.



No comments:

Post a Comment

hard drive - Leaving bad sectors in unformatted partition?

Laptop was acting really weird, and copy and seek times were really slow, so I decided to scan the hard drive surface. I have a couple hundr...