[英]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
的函數。
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.