简体   繁体   English

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

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

I can compile the following code: 我可以编译以下代码:

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

But I can't compile: 但是我不能编译:

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

I get the following error at compile time: 在编译时出现以下错误:

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

EDIT: the thread is joined before unique_ptr goes out of scope 编辑:在unique_ptr超出范围之前已加入线程

What's different between the 2 versions? 这两个版本之间有什么区别? Can I make the second solution work? 我可以使第二个解决方案起作用吗?

Additionally, it seems better to pass by reference a pointer to the managed object than the unique_ptr by reference itself (the threadFunc only has to modify the content of buffer ). 此外,通过引用传递指向托管对象的指针似乎比通过引用本身传递unique_ptr更好(threadFunc只需修改buffer的内容)。 Something like: 就像是:

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

Would this be bad practice? 这是不好的做法吗? Or is this acceptable as well? 还是可以接受? It seems to me that if I want to change the content of buffer, this is what I should pass to the thread function, not the unique_ptr itself? 在我看来,如果我想更改缓冲区的内容,这应该传递给线程函数,而不是unique_ptr本身? Any recommendation would be appreciated. 任何建议,将不胜感激。

EDIT 2: 编辑2:

So According to one of the answers below, the second option is not possible because std::ref(buffer.get()) uses some temp object. 因此,根据以下答案之一,第二个选项是不可能的,因为std::ref(buffer.get())使用了一些临时对象。 Though the first version despite what's said should work (I can't see why this would be invalid): 尽管尽管说了什么,第一个版本还是可以的(我看不出为什么这是无效的):

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));

same as: 如同:

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

As for the solution provided: 至于提供的解决方案:

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

It seems invalid to me as buffer is passed by value and not by reference, however I need to write to buffer. 对我来说似乎无效,因为buffer是通过值而不是通过引用传递的,但是我需要写入缓冲区。 So it needs to be passed by ref. 因此,它需要由ref传递。

If someone could clarify it would be great. 如果有人可以澄清,那就太好了。

The reason why it doesn't work is because your are trying to get a ref to the temporary object. 它不起作用的原因是因为您正在尝试获取对临时对象的引用。 And you can't do this, because reference_wrapper inside it just has the pointer, and it refuses to hold the pointer to the temporary object. 而且您无法执行此操作,因为其中的reference_wrapper仅包含指针,并且它拒绝保留指向临时对象的指针。 It is likely that the version which compiles is actually wrong, as you are passing a pointer to the managed object, which is probably deleted while in use in other thread (unless the thread is joined before unique_ptr goes out of scope) 可能是编译的版本实际上是错误的,因为您传递了一个指向托管对象的指针,该托管对象在其他线程中使用时可能会被删除(除非在unique_ptr超出范围之前加入了该线程)

By the way, unique_ptr was designed exactly to relieve you from those woes. 顺便说一句,unique_ptr的设计正是为了减轻您的麻烦。 Just pass unique_ptr by value, and let the other thread manage it's lifetime. 只需按值传递unique_ptr,然后让另一个线程管理它的生命周期。

Edit: From our discussion, it seems threads are joined before unique_ptr goes out of scope. 编辑:从我们的讨论来看,似乎在unique_ptr超出范围之前已加入线程。 If my understanding is right, you do not need to provide unique_ptr to thread function at all. 如果我的理解是正确的,则根本不需要为线程函数提供unique_ptr。 Following is a perfectly fine (pseudo)code: 以下是一个非常好的(伪)代码:

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();

On a side note, from the snippet above it is not even clear why unique_ptr is needed - as opposed to simply use local variable and pass an address or ref() to it. 顺便说一句,从上面的代码片段中,甚至不清楚为什么需要unique_ptr,而不是简单地使用局部变量并向其传递地址或ref()。 By I suppose, there are reasons for this I am not aware of :) 我想这是我不知道的原因:)

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

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