簡體   English   中英

將 arguments 傳遞給線程 function 時,轉換何時發生?

[英]When does the conversion happen when passing arguments to thread function?

在閱讀一本關於 c++ 多線程編程的書時,我遇到了下面的一個示例。

    void f(int i,std::string const& s);
    void oops(int some_param)
    {
       char buffer[1024];
       sprintf(buffer, "%i",some_param);
       std::thread t(f,3,buffer);
       t.detach();
    }

在這種情況下,它是指向新線程的局部變量緩沖區的指針,並且很有可能 function oops 將在緩沖區轉換為新線程上的 std::string 之前退出,從而導致到未定義的行為。

我知道它是 char* 類型的參數緩沖區,而不是 std::string 被復制到線程 t 的內部存儲中。 讓我感到困惑的是,即使已經構造了線程 t,也有可能沒有發生從 char* 到 std::string 的轉換。 那么什么時候會發生轉換呢? 是在操作系統計划執行線程之前嗎?

正如您所說,數組參數衰減為char* ,然后為線程復制。 更具體地說,新創建的線程基本上執行以下表達式:

std::invoke(auto(std::forward<F>(f)), auto(std::forward<Args>(args))...)

其中fargsstd::thread構造函數的參數,而auto(/*...*/)是新的 C++23 語法,它從參數創建參數衰減類型的純右值(並具體化一個臨時的 object 綁定到std::invoke的參數中的引用時)。

但是,在此評估中,臨時對象auto(/*...*/)的具體化是在線程構造函數的調用者的上下文中執行的,並且對std::invoke的調用的開始與std::thread構造函數。

這意味着auto(/*...*)衰減參數副本是在線程開始執行之前制作的,但其他一切都是作為新執行線程的一部分發生的。

所以auto(buffer)將給出一個char*類型的臨時 object ,它一直存在到線程 function 調用結束(因為臨時對象一直存在到創建它們的完整表達式結束)。 然后std::invoke並引用這個臨時 object 作為參數。 此調用發生在新創建的執行線程中,並且此處的所有內容都與原始線程中執行的 rest 不同步。

std::invoke基本上調用復制的f作為第一個參數並將另一個 arguments 轉發給f 現在,由於您的f期望std::string const&作為第二個參數,但std::invoke會將其傳遞一個char*作為參數,因此將從char*初始化一個臨時的std::string ,用於引用綁定至。 因此,這種構造發生在std::invoke調用的上下文中,該調用已經與主線程中指針指向的數組的潛在破壞不同步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM