线程和解构的仿函数

时间:2017-09-18 21:59:26

标签: c++ multithreading move

我正在尝试理解何时将该仿函数传递给()时调用仿函数(即具有thread运算符的类)的解构函数。但是在下面的例子中,构造函数被调用一次,但解构函数被调用了三次?

根据

  • 对构造函数的缺少(两个)调用是什么?是复制还是移动?
  • 如果调用移动构造函数,如何编写解构函数以便它不会破坏正在移动的资源?想象一下,我打开一个文件run()并在~run()中将其关闭,调用它三次会导致问题。

示例:

#include <iostream>
#include <thread>

using namespace std;

class run {
public:
    run() { cout << "in run()" << endl; }
    ~run() { cout << "in ~run()" << endl; }
    void operator()() {};
};

int main() {
    run thread_r;
    thread t(thread_r);
    t.join();
}

提供输出:

in run()
in ~run()
in ~run()
in ~run()

1 个答案:

答案 0 :(得分:5)

规则5,3和零。

如果定义析构函数,编译器仍将生成默认的复制构造函数和赋值运算符。

不幸的是,如果您定义了析构函数,则意味着您对资源释放有一些特殊处理,因此默认的复制和赋值代码将是完全错误的。

这是一个好的做法,我的意思是&#34;总是这样做,没有借口&#34;,至少提供复制构造函数和赋值运算符,即使你删除它们。

如果您打算提供这些服务,您也可以继续编写正确的移动运营商。

#include <iostream>
#include <thread>

using namespace std;

class run {
public:
    run() { cout << "in run()" << endl; }
    run(const run&) { cout << "copied()" << endl; }
    run(run&&) { cout << "moved()" << endl; }
    run& operator=(const run&) { cout << "copy-assigned()" << endl; return *this; }
    run& operator=(run &&) { cout << "move-assigned()" << endl; return *this; }
    ~run() { cout << "in ~run()" << endl; }
    void operator()() {};
};

int main() {
    run thread_r;
    thread t(thread_r);
    t.join();
}

示例输出:

in run()
copied()
moved()
in ~run()
in ~run()
in ~run()

这是一个更新版本,以帮助解释构造函数和析构函数中发生的事情:

#include <iostream>
#include <thread>
#include <vector>

using namespace std;

class run {
public:
    run()
    : lifetime("constructed")
    { 
        cout << lifetime << endl; 
    }

    run(const run& other)
    : lifetime("copied from " + other.lifetime)
    { 
        cout << lifetime << endl; 
    }
    run(run&& other) 
    : lifetime("move-constructed from " + other.lifetime)
    { 
        other.lifetime = "[zombie] - " + other.lifetime;
        cout << lifetime << endl; 
    }
    run& operator=(const run& other) 
    { 
        lifetime = "copy assigned from " + other.lifetime + ", was once " + lifetime; 
        cout << lifetime << endl; 
        return *this; 
    }

    run& operator=(run &&other) 
    { 
        lifetime = "move-assigned from " + other.lifetime + ", was once " + lifetime; 
        other.lifetime = "[zombie] - " + other.lifetime;
        cout << lifetime << endl; 
        return *this; 
    }

    ~run() 
    {
        lifetime = "lifetime ending: " + lifetime;
        cout << lifetime << endl; 
    }

    void operator()() {};

    std::string lifetime;    
};

int main() {
    run thread_r;
    thread t(thread_r);
    t.join();
}

示例输出:

constructed
copied from constructed
move-constructed from copied from constructed
lifetime ending: [zombie] - copied from constructed
lifetime ending: move-constructed from copied from constructed
lifetime ending: constructed

对于任何不确定复制构造函数和移动构造函数的确切行为的人来说,最好在调试器中使用此代码,直到它变得清晰。