与 C++11 函数签名不一致
Inconsistencies with C++11 function signatures
我对函数有疑问,更具体的是函数签名以及如何传递它们。我可能是一个微不足道甚至愚蠢的问题,但我还没有找到满意的答案。
请考虑这个使用 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) is a pointer to a function returning nothing (void)
and a filepointer as argument.
因此,用户必须使用地址运算符传递所需函数的地址。此时,出现几个问题:
1.) 删除地址运算符同样有效,没有抛出编译器警告,代码有效。这不应该是 error/warning 吗?
2.) 如果我使用对函数的引用(例如 unique_ptr<FILE, void(&)(FILE*)>(f, func1)
),它会按预期工作,那么这是传递函数的更好方法吗?
3.) 完全删除中间说明符(例如 unique_ptr<FILE, void()(FILE*)>(f, func1)
)会导致编译器错误,因此通常不可能按值传递函数吗? (如果是,那么通过将函数隐式转换为函数指针来重载 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 是匿名函数对象。
我对函数有疑问,更具体的是函数签名以及如何传递它们。我可能是一个微不足道甚至愚蠢的问题,但我还没有找到满意的答案。
请考虑这个使用 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) is a pointer to a function returning nothing (void) and a filepointer as argument.
因此,用户必须使用地址运算符传递所需函数的地址。此时,出现几个问题:
1.) 删除地址运算符同样有效,没有抛出编译器警告,代码有效。这不应该是 error/warning 吗?
2.) 如果我使用对函数的引用(例如 unique_ptr<FILE, void(&)(FILE*)>(f, func1)
),它会按预期工作,那么这是传递函数的更好方法吗?
3.) 完全删除中间说明符(例如 unique_ptr<FILE, void()(FILE*)>(f, func1)
)会导致编译器错误,因此通常不可能按值传递函数吗? (如果是,那么通过将函数隐式转换为函数指针来重载 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 是匿名函数对象。