C++ 中奇怪的函数声明和 lambdas

Posted

技术标签:

【中文标题】C++ 中奇怪的函数声明和 lambdas【英文标题】:Weird function declaration and lambdas in C++ 【发布时间】:2020-04-14 15:43:29 【问题描述】:

所以我正在浏览一些笔记,但我被一些奇怪的声明弄糊涂了。 在下面的代码段中,您可以看到下面的代码块有一个分配给自动变量的函数

#include<iostream>
using namespace std;
void Hi(int a)
  
    cout << "Hi" << a << endl;


int main()

    auto Print = Hi;
    Print(5);

但是函数(这里的'Hi')没有括号()并且它仍然有效..那么它是如何工作的? 更让我心动的是它的类型是什么?最后,当我们调用该变量时,它会打印“Hi5”。

我对这部分很好奇,因为这只是我们代码的一个示例部分。 我们需要制作一个 for-each 循环函数的工作示例,以使用这种类型在向量中显示值。

我似乎找不到任何线索,因为我什至不知道类型..但是我们的教授确实提到要更好地使用“lambdas”,我在网上查了一下,但我不清楚这是什么。任何提醒都会非常有帮助。

【问题讨论】:

“我什至不知道类型” - 如果您使用适当的调试器或像 Visual Studio 这样的 IDE,您只需将鼠标悬停在变量名称上即可查看其类型。它看起来像一个函数指针。 请教你的教授。 但是函数(这里的'Hi')没有括号(),它仍然有效 -- 没有括号,它是一个函数指针。这与 lambdas 无关。 帮自己一个忙,写成auto Print = &amp;Hi;(*Print)(5); 仅仅因为函数名可以隐式衰减为指针并不意味着你应该这样做。 【参考方案1】:

但是函数(这里的'Hi')没有括号()并且它仍然有效..那么它是如何工作的?

您在这里看到的是一个函数指针,顾名思义,它通常是指向函数的指针。 毕竟,函数只是 CPU 指令,存储在二进制可执行文件中的某个位置,该函数指针指向内存中函数的地址。 我们实际上是在检索那些 CPU 指令的位置,其中使用了引用 (&amp;),这最终等同于 &amp;Hi。 (存在隐式转换,因此编写 Hi 就足够了。)

让我更感兴趣的是它的类型是什么?

它的 void(*Print)(int) 类型,一个 void 类型的函数指针,接受一个整数作为参数。第一个带有取消引用 *() 包含函数的名称,在您的示例中为 Print。 (它可以是任何东西,取决于你的自动变量的名称。)第二个() 表示传递给函数的参数类型,在你的例子中是一个整数,所以有一个int。 由于它是一个有效的类型,你也可以使用 typedef 来定义它:

typedef void(*printHiFunction)(int);

  printHiFunction Print = Hi;
  Print(5);

我们需要制作一个 for-each 循环函数的工作示例,以使用这种类型在向量中显示值。我似乎找不到任何线索,因为我什至不知道类型..但是我们的教授确实提到要更好地使用“lambdas”,我在网上查了一下,但我不清楚它是什么.任何提醒都会非常有帮助。

我不明白您如何仅使用函数指针来实现它(或者当您可以简单地不使用它时有什么用处)。 否则,您的教授可能希望您绝对使用 lambda。 它只是一个匿名临时函数,可以在必要时调用(并像丢弃函数一样相应地丢弃),也可以作为参数传递给函数。 更多信息,您可以参考here。


对于基于范围的循环,您至少需要传入一个向量,您可以将其声明为 const 并像左值一样通过引用传递它,并将函数指针作为第二个参数传递给您的对于每个循环功能。 然后,您可以使用 lambda 代替带有 int 参数的函数指针,以便在 main() 中调用该整数时仅打印该整数:

void ForEach(const std::vector<int>& values, void(*functionPointer)(int))

   for (int value : values)
     functionPointer(value);

int main()

  std::vector<int> values = 1, 2, 3, 4, 5;
  ForEach(values, [](int value)
   std::cout << value << " "; );

输出:1 2 3 4 5

【讨论】:

感谢您的详尽回答。lambda 中的 '[ ]' 是什么意思? @LightYagami [] 位用于捕获变量。在这种情况下,捕获列表为空。 @LightYagami 这是捕获子句,用于指定如何将变量包含在 lambda 表达式中。例如:[=] 属于可以访问所有局部变量(每个变量的副本)的 lambda,[&amp;] 属于可以通过引用访问的 lambda,等等。您还可以包含特定变量,例如您有一个int a 变量,您可以通过在捕获列表[&amp;a] 中提及它来通过引用特别指定它【参考方案2】:

你在这里看到的是一个函数指针。函数指针,顾名思义,指向返回给定类型并接受给定参数列表的函数。 在您的示例中,Print 变量是一个指向函数的指针,该函数返回 void 并接受一个 int 类型的参数。 我建议您阅读this article 中有关函数指针的部分,并按照 Anirban166 的建议,使用带有调试器的 IDE。

【讨论】:

以上是关于C++ 中奇怪的函数声明和 lambdas的主要内容,如果未能解决你的问题,请参考以下文章

你能给我一些 C++ 中奇怪的单行注释的例子吗?

C++ 中奇怪的括号符号,看起来有点像 for each 循环

Xcode中奇怪的promiseKit 6语法行为

python中奇怪的浮点数到整数转换问题

C ++中奇怪的运行时异常

Eclipse 中奇怪的后退按钮(Alt-Left)行为