簡體   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