函子的线程和解构

thread and deconstruction of functors

本文关键字:和解 线程      更新时间:2023-10-16

我试图了解何时将函数的解构器(即带有()运算符的类)传递给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()

5、3和零的规则。

如果定义了击构函数,则编译器仍将生成默认的复制构造函数和分配运算符。

不幸的是,如果您定义了一个破坏者,则意味着您对资源交易进行了一些特殊的处理,因此默认的副本和分配代码将是错误的。

这是一个很好的实践,我的意思是"总是这样,不借口",即使您删除了至少复制的构造函数和分配操作员。

如果您要提供这些,也可以继续写正确的移动操作员。

#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

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