通过引用线程函数

时间:2015-09-22 16:50:25

标签: c++ multithreading unique-ptr

我可以编译以下代码:

void threadFunc(Vec3f *&buffer) {}
...
std::unique_ptr<Vec3f []> buffer(new Vec3f[100]);
Vec3f *b = buffer.get();
std::thread(threadFunc, std::ref(b)).join();

但我无法编译:

std::thread(threadFunc, std::ref(buffer.get())).join();

我在编译时遇到以下错误:

error: use of deleted function ‘void std::ref(const _Tp&&) [with _Tp = Vec3<float>*]’

编辑:在unique_ptr超出范围

之前连接线程

两个版本有什么不同?我可以让第二个解决方案有效吗?

此外,最好通过引用传递一个指向托管对象的指针,而不是通过引用本身传递unique_ptr(threadFunc只需要修改buffer的内容)。类似的东西:

void threadFunc(std::unique_ptr<Vec3f []> &ptr) {}
std::thread(threadFunc, std::ref(buffer)).join();

这会是不好的做法吗?或者这也是可以接受的?在我看来,如果我想改变缓冲区的内容,这是我应该传递给线程函数,而不是unique_ptr本身?任何建议都将不胜感激。

编辑2:

所以根据下面的一个答案,第二个选项是不可能的,因为std::ref(buffer.get())使用了一些临时对象。虽然第一个版本尽管说的应该有用(我不明白为什么这会无效):

Vec3f *tmp = new Vec3f[100];
std::unique_ptr<Vec3f []> buffer = std::unique_ptr<Vec3f []>(tmp);
Vec3f *b = buffet.get(); // address of b == address of tmp
std::thread(threadFunc, std::ref(b));

同样如下:

std::thread(threadFunc, std::ref(tmp));

至于所提供的解决方案:

void threadFunc(Vec3f *buffer) { buffer[0] = 0; // invalid }
Vec3f *buffer = new Vec3f[100];
std::thread(threadFunc, buffer);

对我来说似乎无效,因为buffer是通过值而不是通过引用传递的,但是我需要写入缓冲区。所以需要通过ref。

传递

如果有人能澄清它会很棒。

1 个答案:

答案 0 :(得分:1)

它不起作用的原因是因为你试图获得对临时对象的引用。你不能这样做,因为它里面的reference_wrapper只有指针,它拒绝保持指向临时对象的指针。编译的版本可能实际上是错误的,因为您正在传递指向托管对象的指针,该指针可能在其他线程中使用时被删除(除非在unique_ptr超出范围之前连接线程)

顺便说一句,unique_ptr的设计恰恰是为了让您免受那些困境。只需按值传递unique_ptr,然后让另一个线程管理它的生命周期。

编辑:从我们的讨论开始,似乎在unique_ptr超出范围之前连接了线程。如果我的理解是正确的,你根本不需要为线程函数提供unique_ptr。以下是完美的(伪)代码:

typedef <your type> type_t;
void handle_func(type_t* ptr);
typedef std::unique_ptr<type_t> ptr_t;

ptr_t ptr(new type_t);
std::thread handler(handle_func, ptr.get());
handler.join();

另一方面,从上面的代码片段来看,甚至不清楚为什么需要unique_ptr - 而不是简单地使用局部变量并将地址或ref()传递给它。据我猜想,有理由我不知道:)