std :: map with std :: function value调用析构函数4次,但只构造一个对象

时间:2017-03-08 11:07:31

标签: c++ stdmap std-function

我在Visual Studio(2015)上运行这个非常简单的示例。 由于某种原因,Functor类析构函数被调用了4次。 我假设实现调用自动生成的复制构造函数几次,但我怀疑这里可能存在错误。如果我自己实现一个复制构造函数,我只得到3个析构函数调用,对应于1个默认构造函数调用和2个复制构造函数调用。

#include <functional>
#include <map>
#include <iostream>

using namespace std;

class Functor
{
public:

    Functor()
    {
        cout << "Functor::Functor()" << endl;
    }

    Functor& operator=(const Functor& rhs) = delete;

    ~Functor()
    {
        cout << "Functor::~Functor()" << endl;
    }

    void operator()()
    {
        cout << "Functor::operator()" << endl;
    }

};

int main()
{
    std::map<int, std::function<void(void)>> myMap;

    myMap[1] = Functor();

    return 0;
}

输出:

Functor::Functor()
Functor::~Functor()
Functor::~Functor()
Functor::~Functor()
Functor::~Functor()

如果我自己实现了复制构造函数:

Functor(const Functor& that)
{
    cout << "Functor::Functor(const Functor&)" << endl;
}

输出:

Functor::Functor();
Functor::Functor(const Functor&)
Functor::Functor(const Functor&)
Functor::~Functor()
Functor::~Functor()
Functor::~Functor()

有人可以解释哪些对象被破坏了吗?这里发生了什么?

1 个答案:

答案 0 :(得分:2)

如果你实现自己的拷贝构造函数,那么move-constructor就是 抑制,选择不同的重载。

试试这个:

struct Reporter
{
    Reporter()                           { cout << "Default constructor\n"; }
    Reporter(const Reporter&)            { cout << "Copy constructor\n"; }
    Reporter(Reporter&&)                 { cout << "Move constructor\n"; }
    Reporter& operator=(const Reporter&) { cout << "Assignment operator\n"; return *this; }
    Reporter& operator=(Reporter&&)      { cout << "Move Assignment operator\n"; return *this; }
    ~Reporter()                          { cout << "Destructor"; }
};

让你感兴趣的课程从中继承。

原文中的四个地方可能是:

  • myMap[1]
    这会创建一个默认构造的对象,在被覆盖时会被销毁。
  • Functor()
    这会创建一个在完整表达式结束时被销毁的临时文件。
  • std::function<void(void)> std::function的构造函数可能按值进行参数化, 启用move-semantics
  • } 你的地图超出范围