簡體   English   中英

void(void) 和 void(*)(void) 有什么區別?

[英]What difference between void(void) and void(*)(void)?

void(*)(void)是一個函數指針,而我認為void(void)也是一種表示函數類型的方法。 它在std::function <functional> 中用作模板參數

什么是void(void)以及它與void(*)(void)有何不同?

什么是void(void)以及它與void(*)(void)有何不同?

它們是不同的類型 盡管在許多情況下前者( void(void) )可以隱式轉換為后者( void(*)(void) )。

void(void)類型稱為函數類型 以下也是函數類型:

int (int, int) //this is a function type
void(int)      //this is a function type as well

另一方面, void (*)(void)指向函數類型的指針。 也就是說,它是一個指針,指向一個參數為0且返回類型為void的函數。

TL;博士

  • void(void)是函數類型的規范,它是簽名。
  • void(*)(void)是指向函數的指針。

這些是不同的。


首先,讓我們先說,有時void(void)將被自動視為指向函數的指針(即在參數列表中)。 我們仍然可以顯式地使用void(*)(void) ,但void(void)在這些情況下將是等價的。

// Here, we explicitly state that the f is a pointer to function
void foo(void (*f)(void), int i); 
// Equivalent, f is automatically treated as a pointer to the function
void foo(void f(void), int i);

例如,提到的std::function不是這種情況 兩者的類型不同,但可能具有相似的行為(即我們可以在指向函數的指針上使用函數調用運算符)。

void bar();

// Prints 1
std::cout << std::is_same<void(void), decltype(bar)>::value << '\n'; 
// Prints 1 as well
// Note the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)*>::value << '\n';
// Prints 0
// Note the absence of the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)>::value << '\n';

特別是:

// Ok
std::function<decltype(bar)> fn1 = bar;
// error: variable ‘std::function<void (*)()> fn2’ has initializer but incomplete type
std::function<decltype(bar)*> fn2 = bar;

請注意,我們可以在std::function中“存儲”一個指向成員函數的指針,但即便如此,模板的參數仍然不是指向函數類型的指針,而是一個普通的函數簽名。

struct MyType {
    void func(int) {}
};

int main() {

    // Note, we can't have a member function without an instance of the type
    // Thus we specify the usually implicit first param and the explicit int param
    std::function<void(MyType&, int)> fn_mem = &MyType::func;
    MyType my_object;
    fn_mem(my_object, 21);
    
}

有關std::function的更多信息,請參閱 參考資料 簡而言之,使用std::function代替函數指針與使用智能指針代替原始指針具有相同的 moto。

您可能想知道void(void)int(int)樣式函數類型規范的其他用途,所以這是您可能經常看到的另一個示例:

using func_t = int(int);
// func_ptr_func return a pointer to the func_t type alias
func_t* func_ptr_func();

注意與參數不同,編譯器不會將返回中的函數類型視為指向函數類型的指針。 因此,我們必須在返回的情況下顯式指定指針類型。

// Here, baz is a function that doesn't take any agruments
// And returns a pointer to a function that takes an int argument and "returns" void
void (*baz())(int);

對於void fun(){}std::is_same_v<void(void)>, decltype(fun)>為真; 並且std::is_same_v<void(*)(void)>, decltype(&fun)>為真。 事實上,這些才是他們真正的類型。 但是,標准允許您將類型為void(void)的對象隱式轉換為void(*)(void) (因此您甚至可以編寫(******funptr)() ),這就是我們總是混淆它們的原因.

暫無
暫無

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

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