繁体   English   中英

emplace_back 调用移动构造函数和析构函数

[英]emplace_back calls move constructor, and destructor

我尝试使用 emplace_back 函数将 cBar 类的两个实例放置到向量中。

根据调用 emplace_back 的 引用仅保留向量中的位置,然后“就地”创建新实例。

现在,我尝试尝试一下:

#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 会“就地”创建实例,然后立即调用移动构造函数,然后调用析构函数。

更奇怪的是,在第二个 emplace 的情况下,我看到了预期的行为:只有一个构造函数调用。

我有两个问题:

  1. 如果我只想 emplace_back 项目并且从不使用 push_back,为什么我需要在我的类中定义一个移动构造函数。

  2. 在第一个实例创建的情况下,为什么要调用移动构造函数,然后调用析构函数? 如果我访问第一个实例的数据似乎都是正确的,所以我不知道为什么调用移动构造函数和析构函数。

我使用 Visual Studio 2015。

每一步输出向量大小:

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 ...

2.在第一个实例创建的情况下,为什么移动构造函数,然后调用析构函数?

因为emplace_back插入第二个元素导致重新分配; vector的内部存储需要扩展,旧存储中的元素必须复制/移动到新存储,然后销毁。

您可以提前使用reserve以避免重新分配。

1.如果我只是想emplace_back项目,而从不使用push_back,为什么我需要在我的类中定义一个移动构造函数。

正如上面的解释所说, vector需要通过复制/移动操作来移动元素。 所以你必须为类定义复制或移动构造函数。 对于emplace_backpush_back都是如此,因为它们都将元素添加到vector并可能导致重新分配。

很可能你的向量的容量是 1,当你放入第二个元素时,它必须调整向量的大小。 这可能会变成一堆在内存中移动的东西,以及你看到的症状。

Kerreks 的建议很好。 我建议在每次操作前后打印矢量容量,看看容量变化是否是原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM