繁体   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