首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++高阶函数:声明多个函数时的不同结果

C++高阶函数:声明多个函数时的不同结果
EN

Stack Overflow用户
提问于 2022-05-25 17:13:53
回答 2查看 48关注 0票数 1

我使用高阶函数,当我创建两个实例并将它们分配给变量时,我开始得到不同的结果。

我将问题简化为以下示例:

代码语言:javascript
复制
#include <iostream>

using ColorGetter = int(*)(void);

auto paint(const ColorGetter &f)
{
    return [&]() { return f(); };
}

int colorA() { return 10; }

int colorB() { return 20; }

int main()
{
    auto painter1 = paint(colorA);
    auto painter2 = paint(colorB);
    std::cout << "painter 1 : " << painter1() << "\n";
    std::cout << "painter 2 : " << painter2() << "\n";

    auto p1 = [] () { return colorA(); };
    auto p2 = [] () { return colorB(); };
    std::cout << "p 1 : " << p1() << "\n";
    std::cout << "p 2 : " << p2() << "\n";
}

我的期望是从这两个序列中得到10,然后是20。相反,根据编译器的不同,我得到:

代码语言:javascript
复制
➜  tmp clang++-13 -o out.gcc wrong.cpp&& ./out.gcc       
painter 1 : 10
painter 2 : 20
p 1 : 10
p 2 : 20
➜  tmp g++-11 -o out.gcc wrong.cpp && ./out.gcc
painter 1 : 20
painter 2 : 20
p 1 : 10
p 2 : 20

上面的代码有什么根本问题吗?我没有编译器警告或clang-整洁的问题,至少在我当前的设置。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-25 17:18:22

让我们看看下面的代码:

代码语言:javascript
复制
auto paint(const ColorGetter &f)
{
    return [&]() { return f(); };
}

f参数仅存在于函数paint的生存期内。您的lambda函数通过引用(即[&]位)捕获它,因此您的lambda捕获将引用函数结束后不再存在的变量(引用f)。因此,要返回的对象保持对函数的悬空引用。您在这里看到了未定义的行为,这就是为什么结果因编译器而异的原因。

若要解决此问题,请将代码更改为

代码语言:javascript
复制
auto paint(const ColorGetter &f)
{
    return [=]() { return f(); };
}

这将导致lambda捕获创建存储在f (指向所述函数的指针)中的值的副本,这将超过paint函数。

票数 1
EN

Stack Overflow用户

发布于 2022-05-25 17:19:03

你没有记录一辈子的事。

代码语言:javascript
复制
auto paint(const ColorGetter &f)
{
  return [&]() { return f(); };
}

这捕获了对f的引用。当lambda超过其创建的作用域时,您几乎不应该使用[&]

f是:

代码语言:javascript
复制
auto painter1 = paint(colorA);

在这一行上创建的临时指针。它在语句末尾被丢弃。

所以您的代码,当它执行f()时,会显示出未定义的行为--您正在跟踪一个悬空引用。

简单的解决办法包括:

代码语言:javascript
复制
auto paint(const ColorGetter &f)
{
  return [=]() { return f(); };
}

我还会去掉指针引用:

代码语言:javascript
复制
auto paint(const ColorGetter f)
{
  return [=]() { return f(); };
}

当我在做的时候。盲目地争论const&是一种坏习惯。就像盲目对待事物一样。知道你经过的是什么。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72381803

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档