繁体   English   中英

通过引用线程函数传递unique_ptr的托管对象

[英]Passing the managed object of a unique_ptr by reference to a thread function

我可以编译以下代码:

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传递。

如果有人可以澄清,那就太好了。

它不起作用的原因是因为您正在尝试获取对临时对象的引用。 而且您无法执行此操作,因为其中的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()。 我想这是我不知道的原因:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM