在C++中向lambda传递参数

wn9m85ua  于 2022-12-27  发布在  其他
关注(0)|答案(5)|浏览(215)

我似乎忽略了C++中lambda机制的一些要点。下面是代码:

std::vector<int> vec (5);

int init = 0;
std::generate(begin(vec), end(vec), [init]() mutable { return ++init; });

for (auto item : vec) {
    std::cout << item << " ";
}
std::cout << std::endl << init << std::endl;

如果没有mutable,它就不会编译,因为我在lambda中更改了init
现在,据我所知,lambda是为每个向量的项调用的,其中initnew fresh copy为0,因此,每次都必须返回1,但这段代码的输出是:

    • 1 2 3 4 5

0**
看起来generate在执行开始时只通过copy init捕获了一次。但是为什么呢?它应该这样工作吗?

atmip9wb

atmip9wb1#

现在,据我所知,为每个向量的项调用lambda,并使用init的新副本,其值为0。
这是不正确的。lambda只是创建类并为其提供operator()的另一种方式。lambda的[]部分描述了成员变量以及它们是通过引用还是值捕获的。lambda的()部分是operator()的参数列表,{}部分是该函数的主体。mutable部分告诉编译器将operator()设置为非const,因为默认情况下它是const
所以

[init]() mutable { return ++init; }

变成

struct compiler_generated_name
{
    int init; // we captured by value

    auto operator()() // since we used mutable this is non const
    {
        return ++init;
    }
};

为了简化输入,我在这里使用了一个struct,但是lambda被指定为类类型,因此可以使用class
这意味着init与上次迭代中的init相同,因为您只捕获过一次。

auto generate_lambda()
{
    int foo = 0;
    return [&foo](){ return ++foo; };
}

将在函数返回时给您留下一个对foo的悬空引用,并且使用它是未定义的行为。

zte4gxcn

zte4gxcn2#

lambda是编译器生成的结构,等效于:

struct lambda
{
    int init = 0; // captured value

    auto operator()() // non-const, due to `mutable`
    {
        return ++init;
    }
};

因此,init只在lambda中被捕获和复制一次--多次调用lambda将不会再次捕获init

nwwlzxa7

nwwlzxa73#

您正在处理并看到init的初始值--根据您的期望,您可能要做的是通过引用捕获init.....

std::vector<int> vec (5);

int init = 0;
std::generate(begin(vec), end(vec), [&init]() mutable { return ++init; });

for (auto item : vec) {
    std::cout << item << " ";
}
std::cout << std::endl << init << std::endl;
kadbb459

kadbb4594#

你的错误在这里“现在,据我所知,lambda被称为 * 每个向量的项目 * 与一个新的新鲜副本的init是0”(我的斜体)。正如你所看到的,lambda是完全独立的,因此对向量代码一无所知。item的初始化发生在每次lambda形式本身被求值时(与每次结果值被调用时相反);这里,这意味着每次调用函数generate时:就一次。

pgvzfuti

pgvzfuti5#

int x = ([](int j)->int {return j; }, 3);

相关问题