std::map 和 std::function 值调用析构函数 4 次但仅构造一个对象

std::map with std::function value calls destructor 4 times but only construct one object

我 运行 这个非常简单的例子 Visual Studio (2015)。 由于某种原因, Functor class 析构函数被调用了 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()

谁能解释一下哪些对象被销毁了?这里发生了什么?

如果你实现自己的复制构造函数,移动构造函数是 被抑制,所以选择了不同的重载。

试试这个:

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"; }
};

并且有您感兴趣的 class 从它继承。

原文中的四个地方大概是:

  • myMap[1]
    这将创建一个默认构造的对象,该对象在被覆盖时被销毁。
  • Functor()
    这会创建一个在完整表达式末尾被销毁的临时文件。
  • std::function<void(void)> std::function 的构造函数可能按值接受它的参数, 启用移动语义
  • } 你的地图超出范围