emplace_back 调用移动构造函数和析构函数
emplace_back calls move constructor, and destructor
我尝试将 class cBar 的两个实例放置到具有 emplace_back 函数的向量中。
根据reference调用一个emplace_back只保留vector中的位置,然后创建新实例"in place".
现在,我试着用它做实验:
#include <vector>
#include <iostream>
#include <memory>
#include <string>
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<cBar> 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;
}
输出:
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 ...
如果你运行上面那个,你会看到第一个emplace_back创建实例"in place",但随后立即调用移动构造函数,然后调用析构函数。
更奇怪的是,在第二个位置的情况下,我看到了预期的行为:只有一个构造函数调用。
我有两个问题:
为什么我需要在我的 class 中定义一个移动构造函数,如果我只想 emplace_back 项目,并且从不使用 push_back.
在第一次创建实例的情况下,为什么先移动构造函数,然后调用析构函数?如果我访问第一个实例的数据似乎都是正确的,所以我不知道为什么调用移动构造函数和析构函数。
我用的是Visual Studio2015.
每一步输出向量大小:
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 ...
很可能你的向量的容量是一个,当你放入第二个元素时,它不得不调整向量的大小。这可以变成一堆东西在记忆中移动,以及你看到的症状。
Kerreks 的建议很好。
我建议在每次操作前后打印向量容量,看看容量变化是否是原因。
2.In case of the first instance creation, why the move constructor, then the destructor is called?
因为emplace_back插入第二个元素导致重新分配; vector
的内部存储需要扩展,旧存储中的元素必须 copied/moved 到新存储,然后销毁。
您可以提前使用reserve
以避免重新分配。
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.
如上面解释所说,vector
需要通过copy/move操作来移动元素。所以你必须为 class 定义复制或移动构造函数。 emplace_back
和 push_back
都是如此,因为它们都将元素添加到 vector
并可能导致重新分配。
我尝试将 class cBar 的两个实例放置到具有 emplace_back 函数的向量中。
根据reference调用一个emplace_back只保留vector中的位置,然后创建新实例"in place".
现在,我试着用它做实验:
#include <vector>
#include <iostream>
#include <memory>
#include <string>
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<cBar> 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;
}
输出:
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 ...
如果你运行上面那个,你会看到第一个emplace_back创建实例"in place",但随后立即调用移动构造函数,然后调用析构函数。
更奇怪的是,在第二个位置的情况下,我看到了预期的行为:只有一个构造函数调用。
我有两个问题:
为什么我需要在我的 class 中定义一个移动构造函数,如果我只想 emplace_back 项目,并且从不使用 push_back.
在第一次创建实例的情况下,为什么先移动构造函数,然后调用析构函数?如果我访问第一个实例的数据似乎都是正确的,所以我不知道为什么调用移动构造函数和析构函数。
我用的是Visual Studio2015.
每一步输出向量大小:
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 ...
很可能你的向量的容量是一个,当你放入第二个元素时,它不得不调整向量的大小。这可以变成一堆东西在记忆中移动,以及你看到的症状。
Kerreks 的建议很好。 我建议在每次操作前后打印向量容量,看看容量变化是否是原因。
2.In case of the first instance creation, why the move constructor, then the destructor is called?
因为emplace_back插入第二个元素导致重新分配; vector
的内部存储需要扩展,旧存储中的元素必须 copied/moved 到新存储,然后销毁。
您可以提前使用reserve
以避免重新分配。
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.
如上面解释所说,vector
需要通过copy/move操作来移动元素。所以你必须为 class 定义复制或移动构造函数。 emplace_back
和 push_back
都是如此,因为它们都将元素添加到 vector
并可能导致重新分配。