与 C++11 函数签名不一致

Inconsistencies with C++11 function signatures

提问人:DocDriven 提问时间:2/8/2022 更新时间:2/11/2022 访问量:76

问:

我有关于函数的问题,更具体地说是关于函数签名以及如何传递它们。我可能是一个微不足道甚至愚蠢的问题,但我还找不到一个令人满意的答案。

请考虑以下示例,它使用 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)

C++ 函数 C++11 -签名

评论

0赞 Dai 2/8/2022
fopen虽然不是惯用的C++ - 将C风格与现代C++混合不是一个好主意。
1赞 user4581301 2/8/2022
shared_ptr是一只奇怪的野兽。除了所选答案之外,还可以查看问题评论和第二个答案,以获得更多范围。
1赞 Passer By 2/8/2022
您可能想从教科书中学习 c++,而不是使用 SO 拼凑。
1赞 Passer By 2/8/2022
@Dai 没关系,它有效,而且是必要的时候。特别是因为它与 .unique_ptr
0赞 Igor Tandetnik 2/8/2022
(1) 您观察到函数到指针的隐式转换(2)“明确”是什么意思?其他方法在哪些方面是“模棱两可的”?(3) 尝试声明一个不带参数并返回函数的函数 - 但一个函数不能返回另一个函数。目前还不清楚你想用它实现什么。void()(FILE*)void(FILE*)

答:

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 是匿名功能对象。