提问人:DocDriven 提问时间:2/8/2022 更新时间:2/11/2022 访问量:76
与 C++11 函数签名不一致
Inconsistencies with C++11 function signatures
问:
我有关于函数的问题,更具体地说是关于函数签名以及如何传递它们。我可能是一个微不足道甚至愚蠢的问题,但我还找不到一个令人满意的答案。
请考虑以下示例,它使用 a 来管理文件指针:std::unique_ptr
#include <iostream>
#include <memory>
void func1(FILE* f)
{
std::cout << "func1 called" << std::endl;
fclose(f);
}
int main()
{
FILE* f = fopen("testfile.txt", "w");
if(f)
{
std::unique_ptr<FILE, void(*)(FILE*)> fptr(f, &func1);
}
return 0;
}
这种智能指针需要函数签名作为第二个模板参数(出于某种奇怪的原因没有)。我目前对这里解释签名的理解是shared_ptr
void () (FILE) 是指向不返回任何内容的函数的指针 (void) 和一个文件指针作为参数。
因此,用户必须使用地址运算符传递所需函数的地址。此时,出现了几个问题:
1.) 删除地址运算符也一样有效,不会抛出编译器警告,代码有效。这不应该是一个错误/警告吗?
2.) 如果我使用对函数的引用(例如 ) 它按预期工作,那么这是传递函数的更好方法吗,因为它是明确的?unique_ptr<FILE, void(&)(FILE*)>(f, func1)
3.) 完全删除中间说明符(例如 ) 会导致编译器错误,那么通常不可能按值传递函数吗?(如果是,那么通过隐式将函数转换为函数指针来重载 1 中的版本是有意义的)unique_ptr<FILE, void()(FILE*)>(f, func1)
答:
1赞
Ivan Vorobyev
2/11/2022
#1
函数名称是函数的始终地址(指向函数的指针)。如果你想使用其他的东西,你可以使用一些包装器,例如 std::function:
#include <iostream>
#include <memory>
#include <functional>
class Closer {
public:
void operator ()(FILE *f) {
std::cout << "func1 called" << std::endl;
fclose(f);
}
};
int main()
{
FILE* f = fopen("testfile.txt", "w");
if(f)
{
std::unique_ptr<FILE, std::function<void(FILE*)>> fptr(f, Closer());
}
return 0;
}
在这种情况下,Lambda 是匿名功能对象。
评论
fopen
虽然不是惯用的C++ - 将C风格与现代C++混合不是一个好主意。shared_ptr
是一只奇怪的野兽。除了所选答案之外,还可以查看问题评论和第二个答案,以获得更多范围。unique_ptr
void()(FILE*)
void(FILE*)