Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否有一些函数不';我不会虚度光阴*?_C++_Posix_Higher Order Functions - Fatal编程技术网

C++ 是否有一些函数不';我不会虚度光阴*?

C++ 是否有一些函数不';我不会虚度光阴*?,c++,posix,higher-order-functions,C++,Posix,Higher Order Functions,许多函数接受函数指针作为参数atexit和call_once都是很好的例子。如果这些更高级别的函数接受void*参数,例如atexit(&myFunction,&argumentForMyFunction),那么我可以通过传递函数指针和数据块来轻松包装任何我喜欢的函子,以提供状态性 在很多情况下,我希望可以使用参数注册回调,但注册函数不允许传递任何参数atexit只接受一个参数:一个接受0个参数的函数。我不能注册一个函数来清理我的对象,我必须注册一个函数来清理一个类的所有对象,并强制我的类维护一

许多函数接受函数指针作为参数
atexit
call_once
都是很好的例子。如果这些更高级别的函数接受void*参数,例如
atexit(&myFunction,&argumentForMyFunction)
,那么我可以通过传递函数指针和数据块来轻松包装任何我喜欢的函子,以提供状态性

在很多情况下,我希望可以使用参数注册回调,但注册函数不允许传递任何参数
atexit
只接受一个参数:一个接受0个参数的函数。我不能注册一个函数来清理我的对象,我必须注册一个函数来清理一个类的所有对象,并强制我的类维护一个需要清理的所有对象的列表

我一直认为这是一个疏忽,似乎没有正当理由不允许传递微不足道的4或8字节指针,除非您使用的是极其有限的微控制器。我一直认为,直到重新定义规范为时已晚,他们才意识到额外参数的重要性。在
call_once
的情况下,posix版本不接受任何参数,但C++11版本接受一个函子(这实际上相当于传递一个函数和一个参数,只有编译器为您做一些工作)


有什么理由不允许额外的参数吗?只接受“0参数的void函数”有什么好处吗相当多的使用函数指针但没有传递参数的接口只是来自不同的时代。然而,如果不破坏现有代码,就无法更改它们的签名。这是一种设计错误,但事后看来很容易说出来。整体编程风格已经转向对函数的有限使用通常是非函数式编程语言中的非函数式编程。此外,在创建这些接口时,即使在“普通”计算机上存储任何额外数据也意味着可观的额外成本:除了使用的额外存储之外,即使不使用额外参数,也需要传递额外参数。当然,
atexit()
几乎不一定会成为性能瓶颈,因为它只被调用一次,但是如果您在任何地方都传递一个额外的指针,那么肯定还会有一个
qsort()
的比较函数

特别是对于像
atexit()
这样的东西,使用自定义全局对象注册退出时要调用的函数对象是合理的:只需使用
atexit()
注册一个函数,调用用所述全局对象注册的所有函数即可。还要注意
atexit()
只保证注册多达32个函数,尽管实现可能支持更多注册函数。似乎不建议将其用作对象清理函数的注册表,而不是调用对象清理函数的函数,因为其他库可能也需要注册函数


也就是说,我无法想象为什么
atexit()在C++中特别有用,在那里,对象在程序终止时自动被销毁。当然,这种方法假定所有的对象都被某种方式所保存,但无论如何都是必要的,通常是用适当的对象来完成的。

< P>我认为<代码> ATS/<代码>只是一个特殊的例子,BEC。因为传递给它的任何函数都应该只调用一次。因此,它需要执行其任务的任何状态都可以保存在全局变量中。如果
atexit
是今天设计的,它可能需要一个
void*
来避免使用全局变量,但这实际上不会给它任何好处新功能;在某些情况下,它只会使代码稍微干净一些


但是,对于许多API,回调可以接受额外的参数,不允许它们这样做将是一个严重的设计缺陷。例如,
pthread\u create
允许您传递一个
void*
,这很有意义,因为否则每个线程都需要一个单独的函数,并且完全不可能编写生成可变线程数的程序。

在使用全局状态的情况下,编写自己的处理程序,将其分派给您喜欢的任何一个函子或函子列表,这并不丢脸。您可以使用全局变量存储该函子或函子列表,但实际上并没有什么好处你的程序越来越讨厌了。因此,对于
atexit
,答案是没有意义。
std::call\u once
接受任意的函数对象和任意数量的参数。至于
atexit()
,由于保证支持的回调数量有限,我不确定“为创建的每个对象注册一个函数”这是一个好主意(尽管您的基本问题仍然正确)。我同意,几乎所有采用回调函数的API都应该提供一种将上下文传递给回调函数的方法(在C语言中,通常的方法是通过
void*
).我不知道你的问题是什么-如果你需要使用这些函数,那么这些函数就没有了。缺少一些上下文参数是设计这些接口的人的疏忽吗?是的,可能是。在
atexit()的特定情况下您可能想考虑<代码> ONEXEIT()/<代码>,除非POSIX符合性是一个严格的要求。