具有对象的右值引用的线程

thread with rvalue reference of an object

本文关键字:引用 线程 对象      更新时间:2023-10-16

我有一个函数,它接受对象的右值引用,我想在std::thread中运行这个函数。以下代码段

#include <iostream>
#include <thread>
class MyType {
public:
explicit MyType(int m) : myint_(m) {}
MyType(const MyType& ) = delete;
MyType ( MyType&& ) = delete;
MyType operator = (const MyType& ) = delete;
MyType operator = (const MyType&&) = delete;
private:
int myint_;
};
void Run(const MyType&& t) {
// do somthing with t.     
}
int main()
{
MyType m{100};
std::thread t(Run, std::move(m));
t.join();
return 0;
}

我已经删除了默认的移动和复制构造函数。就我而言,可以定义一个默认的移动构造函数,但我不希望有一个复制构造函数sizeof(MyType),因为它可能很大,而且我担心调用复制构造函数时的内存。

我需要有关如何实现这一目标的建议。

问候。

多亏了@SamVarshavchik,我现在让它与std::unique_ptr一起工作

#include <iostream>
#include <thread>
class MyType {
public:
explicit MyType(int m) : myint_(m) {}
MyType(const MyType& ) = delete;
MyType ( MyType&& ) = delete;
MyType operator = (const MyType& ) = delete;
MyType operator = (const MyType&&) = delete;
private:
int myint_;
};
void Run(std::unique_ptr<MyType>&& t) {
// do somthing with t.     
}
int main()
{
auto m = std::make_unique<MyType>(100);
std::thread t(Run, std::move(m));
t.join();
return 0;
}

后续问题:unique_ptr不可复制,只能移动。它如何与它一起使用,但不适用于我的数据类型(即使我使其可移动(?

发生的事情是std::thread将其参数复制到类似元组的东西中,然后在线程中使用这些参数调用函数。

在特定情况下,线程的寿命不会超过创建std::thread对象的范围。 这不是典型的。

获得您想要工作的最简单方法是:

MyType m{100};
std::thread t([&]{ Run(std::move(m)); });
t.join();

您传入 lambda 并自己管理复制和生命周期的地方。

请注意,如果此线程的寿命超过创建m的范围,则将遵循悬而未决的引用。

std::thread t([pm=std::make_unique<MyType>(100)]() mutable { Run(std::move(*pm)); });

是一个版本,我直接在堆上创建对象,然后使用智能指针随线程携带它。 正确编写的std::thread应该只需要其可调用的可移动(编写不正确的可调用将它存储在 std 函数中可能会在此处生成构建错误;您可以将唯一的 ptr 换成共享的 PTR,以获得适度的额外开销,但让它在不符合标准的 std 线程上编译(。


我的一般经验法则是不使用基于 INVOKE 的线程帮助程序,而是使用无参数 lambda 并处理参数存储和传递自己。

线程 API 来自 C++ 年前 lambda 时代的 boost;lambda 是你真正应该掌握的东西,并且可以取代在基于 INVOKE 的 API 的怪癖方面获得专业知识(即使知道 INVOKE 是什么,你也不需要知道!

(std::invokestd::apply,OTOH,很棒,即使它们是调用的;我的主要抱怨是违反了SRP(单一责任原则(,我们将线程结构与调用结构混合在一起。