簡體   English   中英

我可以安全地轉換為返回void的函數嗎?

[英]Can I safely cast to a function returning void?

由於明顯的原因,在采用不同參數或返回不同類型的函數類型之間進行轉換是不安全的。

(對我而言)不明顯的是,將安全類型強制轉換為返回類型為void(且參數類型相同)的函數指針類型是否安全。

是否存在將int (*)() void (*)()void (*)() static_cast在這里失敗。 reinterpret_cast有效,但是不安全。

有沒有安全的方法?

std::function<void()>(funcReturningInt)似乎可以解決問題,但是我似乎無法通過迷宮實現來了解它。

根據標准,沒有安全的轉換

[expr.reinterpret.cast] / 6一個函數指針可以顯式轉換為其他類型的函數指針。 [ 注意:通過指向與函數定義中使用的類型不同的函數類型(11.3.5)的指針調用函數的效果是不確定的。 — [end note ]除了將類型為“ pointer to T1 ”的prvalue轉換為類型“ pointer to T2 ”(其中T1T2是函數類型)並返回其原始類型會產生原始指針值,這種處理的結果指針轉換未指定。

希望這可以幫助。

沒有安全的演員表。

根據c ++標准的答案由另一個答案給出,在這里我實際上要解釋為什么會這樣。

處理返回值的方法有很多,C / C ++沒有定義或限制如何處理返回值。 它們在ABI中定義。

X86 ABI內部定義了幾種調用約定,例如cdeclstdcallthiscall 不同的調用約定對返回值的處理方式不同,這里最相關的事實是返回值存儲在何處。

如果返回值存儲在堆棧內部,則調用者必須在獲取返回值之后調整堆棧指針。 在這種情況下,如果將返回值轉換為void,則調用者將無法調整堆棧指針,通常情況下,堆棧已損壞,這通常會導致崩潰。

如果將返回值存儲在寄存器中,則調用方可以假定在調用返回void的函數時未修改這些寄存器,但是如果沒有,則被調用方可以修改這些寄存器。 分歧也可能導致崩潰。

如果您堅持使用強制類型轉換,則只需確保選擇正確的調用約定即可,即返回值不受影響。

正如其他人指出的那樣,演員陣容並不安全。 而且std::function是不必要的。 如果要將函數傳遞給期望指向void函數的指針的東西而忽略返回結果,則可以使用lambda輕松實現:

int foo();

auto gimme_gimme_a_function_after_midnight(void (*f)() )
{
    f();
}

auto test()
{
    gimme_gimme_a_function_after_midnight([]() { foo(); });
}

lambda只是調用該函數,而忽略返回的值。 並且由於它沒有捕獲,因此可以隱式轉換為函數指針。

如果函數具有易於調整的參數。

為了完整起見,std :: function的實現方式是通過模板化構造函數。 模板化構造函數可為請求存儲的每種簽名類型有效地創建靜態簽名適配器函數,並保留相當於存儲函數的void指針和適配器函數的函數指針的值。

在調用時,它使用void指針調用適配器函數,並將其重新投射回原始類型。

暫無
暫無

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

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