函子的线程和解构
thread and deconstruction of functors
我试图了解何时将函数的解构器(即带有()
运算符的类)传递给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
对于任何不确定复制构造函数和移动构建器的确切行为的人来说,最好在调试器中使用此代码,直到清楚为止。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 用于矢量处理的多个线程
- 在任何地方对C++中所有并行线程中的所有锁定和解锁实例使用相同的 std::mutex 和 lock 对象
- 函子的线程和解构