函数内部可以有函数吗?

时间:2022-03-22 21:26:17

I mean something like:

我的意思是类似的:

int main() 
{
  void a() 
  {
      // code
  }
  a();

  return 0;
}

12 个解决方案

#1


147  

No, C++ doesn't support that.

不,c++不支持这个。

Edit: This answer is old. Meanwhile, C++11 has lambdas which can achieve a similar result – see answers below.

编辑:这个答案已经过时了。与此同时,c++ 11也有lambdas,它可以得到类似的结果——请参阅下面的答案。

That said, you can have local classes, and they can have functions (non-static or static), so you can get this to some extend, albeit it's a bit of a kludge:

也就是说,你可以有本地类,它们可以有函数(非静态的或静态的),所以你可以把它扩展一些,尽管它有点复杂:

int main() // it's int, dammit!
{
  struct X { // struct's as good as class
    static void a()
    {
    }
  };

  X::a();

  return 0;
}

However, I'd question the praxis. Everyone knows (well, now that you do, anyway :)) C++ doesn't support local functions, so they are used to not having them. They are not used, however, to that kludge. I would spend quite a while on this code to make sure it's really only there to allow local functions. Not good.

然而,我对实践提出了质疑。每个人都知道(好吧,现在你已经知道了)c++不支持本地函数,所以它们已经习惯不支持本地函数了。然而,它们并没有被用在那些笨拙的人身上。我花了很长时间在这段代码上,以确保它只允许本地函数。不好的。

#2


206  

For all intents and purposes, C++ supports this via lambdas:1

对于所有意图和目的,c++通过lambdas:1提供支持。

int main() {
    auto f = []() { return 42; };
    std::cout << "f() = " << f() << std::endl;
}

Here, f is a lambda object that acts as a local function in main. Captures can be specified to allow the function to access local objects.

在这里,f是一个lambda对象,在main中充当局部函数。可以指定捕获以允许函数访问本地对象。

Behind the scenes, f is a function object (i.e. an object of a type that provides an operator()). The function object type is created by the compiler based on the lambda.

在幕后,f是一个函数对象(即提供运算符()的类型的对象)。函数对象类型是由编译器基于lambda创建的。


1 since C++11

1,因为c++ 11

#3


32  

Local classes have already been mentioned, but here is a way to let them appear even more as local functions, using an operator() overload and an anonymous class:

已经提到了本地类,但是这里有一种方法可以让它们更像本地函数,使用操作符()重载和匿名类:

int main() {
    struct {
        unsigned int operator() (unsigned int val) const {
            return val<=1 ? 1 : val*(*this)(val-1);
        }
    } fac;

    std::cout << fac(5) << '\n';
}

I don't advise on using this, it's just a funny trick (can do, but imho shouldn't).

我不建议使用这个,这只是一个有趣的技巧(可以,但是imho不应该)。


2014 Update:

With the rise of C++11 a while back, you can now have local functions whose syntax is a little reminiscient of JavaScript:

随着c++ 11的崛起,您现在可以使用本地函数,其语法有点像JavaScript:

auto fac = [] (unsigned int val) {
    return val*42;
};

#4


14  

No.

不。

What are you trying to do?

你想做什么?

workaround:

处理:

int main(void)
{
  struct foo
  {
    void operator()() { int a = 1; }
  };

  foo b;
  b(); // call the operator()

}

#5


9  

You can, sort-of, but you have to cheat and use a dummy class:

你可以,但你必须欺骗,使用一个虚拟的类:

void moo()
{
    class dummy
    {
    public:
         static void a() { printf("I'm in a!\n"); }
    };

    dummy::a();
    dummy::a();
}

#6


7  

No, it's not allowed. Neither C nor C++ support this feature by default, however TonyK points out (in the comments) that there are extensions to the GNU C compiler that enable this behavior in C.

不,这是不允许的。C和c++在默认情况下都不支持这个特性,不过TonyK在注释中指出,gnuc编译器有扩展,可以在C中支持这种行为。

#7


6  

You cannot define a free function inside another in C++.

不能在c++中定义一个*函数。

#8


6  

As others have mentioned, you can use nested functions by using the gnu language extensions in gcc. If you (or your project) sticks to the gcc toolchain, your code will be mostly portable across the different architectures targeted by the gcc compiler.

正如其他人提到的,您可以使用gcc中的gnu语言扩展来使用嵌套函数。如果您(或您的项目)坚持使用gcc工具链,那么您的代码将主要在gcc编译器针对的不同体系结构中是可移植的。

However, if there is a possible requirement that you might need to compile code with a different toolchain, then I'd stay away from such extensions.

但是,如果您可能需要使用不同的工具链编译代码,那么我将远离这种扩展。


I'd also tread with care when using nested functions. They are a beautiful solution for managing the structure of complex, yet cohesive blocks of code (the pieces of which are not meant for external/general use.) They are also very helpful in controlling namespace pollution (a very real concern with naturally complex/long classes in verbose languages.)

在使用嵌套函数时,我也会格外小心。它们是管理复杂的、但有粘性的代码块结构的漂亮解决方案(这些代码块不是用于外部/一般用途的)。它们在控制命名空间污染方面也非常有用(在冗长的语言中,这是对自然复杂/长类的真正关注)。

But like anything, they can be open to abuse.

但和任何事情一样,它们也可能被滥用。

It is sad that C/C++ does not support such features as an standard. Most pascal variants and Ada do (almost all Algol-based languages do). Same with JavaScript. Same with modern languages like Scala. Same with venerable languages like Erlang, Lisp or Python.

令人遗憾的是,C/ c++不支持这样的特性作为标准。大多数pascal变体和Ada do(几乎所有基于algolde的语言都是这样做的)。相同的JavaScript。像Scala这样的现代语言也是如此。像Erlang、Lisp或Python之类的古老语言也是如此。

And just as with C/C++, unfortunately, Java (with which I earn most of my living) does not.

不幸的是,就像C/ c++一样,Java(我的大部分生活都是靠它维生的)也不是。

I mention Java here because I see several posters suggesting usage of classes and class' methods as alternatives to nested functions. And that's also the typical workaround in Java.

我在这里提到Java是因为我看到了一些海报,它们建议使用类和类的方法来替代嵌套函数。这也是Java中典型的解决方案。

Short answer: No.

简短的回答:没有。

Doing so tend to introduce artificial, needless complexity on a class hierarchy. With all things being equal, the ideal is to have a class hierarchy (and its encompassing namespaces and scopes) representing an actual domain as simple as possible.

这样做往往会在类层次结构中引入人为的、不必要的复杂性。在所有条件都相同的情况下,理想的方法是拥有一个类层次结构(及其包含的名称空间和范围),以尽可能简单地表示一个实际的域。

Nested functions help deal with "private", within-function complexity. Lacking those facilities, one should try to avoid propagating that "private" complexity out and into one's class model.

嵌套函数有助于处理“私有”、功能内部的复杂性。由于缺乏这些设施,我们应该尽量避免将“私有”的复杂性传播到一个人的类模型中。

In software (and in any engineering discipline), modeling is a matter of trade-offs. Thus, in real life, there will be justified exceptions to those rules (or rather guidelines). Proceed with care, though.

在软件(以及任何工程学科)中,建模是一个权衡取舍的问题。因此,在现实生活中,这些规则(或者更确切地说是指导方针)将有合理的例外。不过,谨慎行事。

#9


4  

All this tricks just look (more or less) as local functions, but they don't work like that. In a local function you can use local variables of it's super functions. It's kind of semi-globals. Non of these tricks can do that. The closest is the lambda trick from c++0x, but it's closure is bound in definition time, not the use time.

所有这些技巧看起来(或多或少)都是局部函数,但它们不是这样工作的。在局部函数中,可以使用它的超函数的局部变量。这是一种semi-globals。这些把戏都做不到。最接近的是c++0x的lambda技巧,但是它的闭包是在定义时间而不是使用时间内绑定的。

#10


3  

Let me post a solution here for C++03 that I consider the cleanest possible.*

我在这里发布一个c++ 03的解决方案,我认为它是最干净的

#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
    struct { RETURN_TYPE operator () FUNCTION } NAME;

...

int main(){
  DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
  demoLambda();

  DECLARE_LAMBDA(plus, int, (int i, int j){
    return i+j;
  });
  cout << "plus(1,2)=" << plus(1,2) << endl;
  return 0;
}

(*) in the C++ world using macros is never considered clean.

(*)在c++世界中,使用宏从来不被认为是干净的。

#11


3  

You can't have local functions in C++. However, C++11 has lambdas. Lambdas are basically variables that work like functions.

在c++中不能有本地函数。然而,C + + 11λ。lambda本质上是与函数类似的变量。

A lambda has the type std::function (actually that's not quite true, but in most cases you can suppose it is). To use this type, you need to #include <functional>. std::function is a template, taking as template argument the return type and the argument types, with the syntax std::function<ReturnType(ArgumentTypes). For example, std::function<int(std::string, float)> is a lambda returning an int and taking two arguments, one std::string and one float. The most common one is std::function<void()>, which returns nothing and takes no arguments.

lambda具有std:::function类型(实际上这不是完全正确的,但在大多数情况下您可以假定它是正确的)。要使用这种类型,您需要#include 。函数是一个模板,以返回类型和参数类型作为模板参数,语法std::function 是一个返回int并接受两个参数,一个std::string和一个float。最常见的是std::function ,它不返回任何东西,不接受任何参数。 ()> (argumenttypes)。例如,std::函数

Once a lambda is declared, it is called just like a normal function, using the syntax lambda(arguments).

一旦一个lambda被声明,它就会像一个普通函数一样被调用,使用语法lambda(参数)。

To define a lambda, use the syntax [captures](arguments){code} (there are other ways of doing it, but I won't mention them here). arguments is what arguments the lambda takes, and code is the code that should be run when the lambda is called. Usually you put [=] or [&] as captures. [=] means that you capture all variables in the scope in which the value is defined by value, which means that they will keep the value that they had when the lambda was declared. [&] means that you capture all variables in the scope by reference, which means that they will always have their current value, but if they are erased from memory the program will crash. Here are some examples:

要定义lambda,请使用语法[capture](参数){code}(还有其他方法,但这里不提)。参数是lambda使用的参数,而代码是在调用lambda时应该运行的代码。通常你把[=]或[&]作为捕获。[=]表示您捕获了值由值定义的范围内的所有变量,这意味着它们将保留声明lambda时的值。[&]意味着您通过引用捕获范围中的所有变量,这意味着它们将始终具有它们的当前值,但是如果从内存中删除它们,程序将崩溃。下面是一些例子:

#include <functional>
#include <iostream>

int main(){
    int x = 1;

    std::function<void()> lambda1 = [=](){
        std::cout << x << std::endl;
    };
    std::function<void()> lambda2 = [&](){
        std::cout << x << std::endl;
    };

    x = 2;
    lambda1();    //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
    lambda2();    //Prints 2 since that's the current value of x and x was captured by value with [&]

    std::function<void()> lambda3 = [](){}, lambda4 = [](){};    //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
                                                                 //[](){} is the empty lambda.

    {
        int y = 3;    //y will be deleted from the memory at the end of this scope
        lambda3 = [=](){
            std::cout << y << endl;
        };
        lambda4 = [&](){
            std::cout << y << endl;
        };
    }

    lambda3();    //Prints 3, since that's the value y had when it was captured

    lambda4();    //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
                  //This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
                  //This is why you should be careful when capturing by reference.

    return 0;
}

You can also capture specific variables by specifying their names. Just specifying their name will capture them by value, specifying their name with a & before will capture them by reference. For example, [=, &foo] will capture all variables by value except foo which will be captured by reference, and [&, foo] will capture all variables by reference except foo which will be captured by value. You can also capture only specific variables, for example [&foo] will capture foo by reference and will capture no other variables. You can also capture no variables at all by using []. If you try to use a variable in a lambda that you didn't capture, it won't compile. Here is an example:

您还可以通过指定它们的名称来捕获特定的变量。只需指定它们的名称,就可以按值捕获它们,使用& before指定它们的名称,就可以通过引用捕获它们。例如,[=,&foo]将按值捕获除foo外的所有变量,而[&,foo]将通过引用捕获除foo外的所有变量,而foo将被值捕获。您还可以只捕获特定的变量,例如[&foo]将根据引用捕获foo,并且不会捕获其他变量。您还可以使用[]来捕获所有变量。如果您试图在lambda中使用一个未捕获的变量,它将不会编译。这是一个例子:

#include <functional>

int main(){
    int x = 4, y = 5;

    std::function<void(int)> myLambda = [y](int z){
        int xSquare = x * x;    //Compiler error because x wasn't captured
        int ySquare = y * y;    //OK because y was captured
        int zSquare = z * z;    //OK because z is an argument of the lambda
    };

    return 0;
}

You can't change the value of a variable that was captured by value inside a lambda (variables captured by value have a const type inside the lambda). To do so, you need to capture the variable by reference. Here is an exampmle:

您不能更改lambda中值捕获的变量的值(值捕获的变量在lambda中具有const类型)。为此,需要根据引用捕获变量。这是一个exampmle:

#include <functional>

int main(){
    int x = 3, y = 5;
    std::function<void()> myLambda = [x, &y](){
        x = 2;    //Compiler error because x is captured by value and so it's of type const int inside the lambda
        y = 2;    //OK because y is captured by reference
    };
    x = 2;    //This is of course OK because we're not inside the lambda
    return 0;
}

Also, calling uninitialized lambdas is undefined behavior and will usually cause the program to crash. For example, never do this:

另外,调用未初始化的lambdas是一种未定义的行为,通常会导致程序崩溃。例如,千万不要这样做:

std::function<void()> lambda;
lambda();    //Undefined behavior because lambda is uninitialized

Examples

例子

Here is the code for what you wanted to do in your question using lambdas:

这里是你想用lambdas做的问题的代码:

#include <functional>    //Don't forget this, otherwise you won't be able to use the std::function type

int main(){
    std::function<void()> a = [](){
        // code
    }
    a();
    return 0;
}

Here is a more advanced example of a lambda:

这里有一个关于lambda的更高级的例子:

#include <functional>    //For std::function
#include <iostream>      //For std::cout

int main(){
    int x = 4;
    std::function<float(int)> divideByX = [x](int y){
        return (float)y / (float)x;    //x is a captured variable, y is an argument
    }
    std::cout << divideByX(3) << std::endl;    //Prints 0.75
    return 0;
}

#12


2  

But we can declare a function inside main():

但我们可以在main()中声明一个函数:

int main()
{
    void a();
}

Although the syntax is correct, sometimes it can lead to the "Most vexing parse":

虽然语法是正确的,但有时它会导致“最烦人的解析”:

#include <iostream>


struct U
{
    U() : val(0) {}
    U(int val) : val(val) {}

    int val;
};

struct V
{
    V(U a, U b)
    {
        std::cout << "V(" << a.val << ", " << b.val << ");\n";
    }
    ~V()
    {
        std::cout << "~V();\n";
    }
};

int main()
{
    int five = 5;
    V v(U(five), U());
}

=> no program output.

= >没有程序输出。

(Only Clang warning after compilation).

(编译后仅发出叮当警告)。

C++'s most vexing parse again

c++最烦人的解析再次出现

#1


147  

No, C++ doesn't support that.

不,c++不支持这个。

Edit: This answer is old. Meanwhile, C++11 has lambdas which can achieve a similar result – see answers below.

编辑:这个答案已经过时了。与此同时,c++ 11也有lambdas,它可以得到类似的结果——请参阅下面的答案。

That said, you can have local classes, and they can have functions (non-static or static), so you can get this to some extend, albeit it's a bit of a kludge:

也就是说,你可以有本地类,它们可以有函数(非静态的或静态的),所以你可以把它扩展一些,尽管它有点复杂:

int main() // it's int, dammit!
{
  struct X { // struct's as good as class
    static void a()
    {
    }
  };

  X::a();

  return 0;
}

However, I'd question the praxis. Everyone knows (well, now that you do, anyway :)) C++ doesn't support local functions, so they are used to not having them. They are not used, however, to that kludge. I would spend quite a while on this code to make sure it's really only there to allow local functions. Not good.

然而,我对实践提出了质疑。每个人都知道(好吧,现在你已经知道了)c++不支持本地函数,所以它们已经习惯不支持本地函数了。然而,它们并没有被用在那些笨拙的人身上。我花了很长时间在这段代码上,以确保它只允许本地函数。不好的。

#2


206  

For all intents and purposes, C++ supports this via lambdas:1

对于所有意图和目的,c++通过lambdas:1提供支持。

int main() {
    auto f = []() { return 42; };
    std::cout << "f() = " << f() << std::endl;
}

Here, f is a lambda object that acts as a local function in main. Captures can be specified to allow the function to access local objects.

在这里,f是一个lambda对象,在main中充当局部函数。可以指定捕获以允许函数访问本地对象。

Behind the scenes, f is a function object (i.e. an object of a type that provides an operator()). The function object type is created by the compiler based on the lambda.

在幕后,f是一个函数对象(即提供运算符()的类型的对象)。函数对象类型是由编译器基于lambda创建的。


1 since C++11

1,因为c++ 11

#3


32  

Local classes have already been mentioned, but here is a way to let them appear even more as local functions, using an operator() overload and an anonymous class:

已经提到了本地类,但是这里有一种方法可以让它们更像本地函数,使用操作符()重载和匿名类:

int main() {
    struct {
        unsigned int operator() (unsigned int val) const {
            return val<=1 ? 1 : val*(*this)(val-1);
        }
    } fac;

    std::cout << fac(5) << '\n';
}

I don't advise on using this, it's just a funny trick (can do, but imho shouldn't).

我不建议使用这个,这只是一个有趣的技巧(可以,但是imho不应该)。


2014 Update:

With the rise of C++11 a while back, you can now have local functions whose syntax is a little reminiscient of JavaScript:

随着c++ 11的崛起,您现在可以使用本地函数,其语法有点像JavaScript:

auto fac = [] (unsigned int val) {
    return val*42;
};

#4


14  

No.

不。

What are you trying to do?

你想做什么?

workaround:

处理:

int main(void)
{
  struct foo
  {
    void operator()() { int a = 1; }
  };

  foo b;
  b(); // call the operator()

}

#5


9  

You can, sort-of, but you have to cheat and use a dummy class:

你可以,但你必须欺骗,使用一个虚拟的类:

void moo()
{
    class dummy
    {
    public:
         static void a() { printf("I'm in a!\n"); }
    };

    dummy::a();
    dummy::a();
}

#6


7  

No, it's not allowed. Neither C nor C++ support this feature by default, however TonyK points out (in the comments) that there are extensions to the GNU C compiler that enable this behavior in C.

不,这是不允许的。C和c++在默认情况下都不支持这个特性,不过TonyK在注释中指出,gnuc编译器有扩展,可以在C中支持这种行为。

#7


6  

You cannot define a free function inside another in C++.

不能在c++中定义一个*函数。

#8


6  

As others have mentioned, you can use nested functions by using the gnu language extensions in gcc. If you (or your project) sticks to the gcc toolchain, your code will be mostly portable across the different architectures targeted by the gcc compiler.

正如其他人提到的,您可以使用gcc中的gnu语言扩展来使用嵌套函数。如果您(或您的项目)坚持使用gcc工具链,那么您的代码将主要在gcc编译器针对的不同体系结构中是可移植的。

However, if there is a possible requirement that you might need to compile code with a different toolchain, then I'd stay away from such extensions.

但是,如果您可能需要使用不同的工具链编译代码,那么我将远离这种扩展。


I'd also tread with care when using nested functions. They are a beautiful solution for managing the structure of complex, yet cohesive blocks of code (the pieces of which are not meant for external/general use.) They are also very helpful in controlling namespace pollution (a very real concern with naturally complex/long classes in verbose languages.)

在使用嵌套函数时,我也会格外小心。它们是管理复杂的、但有粘性的代码块结构的漂亮解决方案(这些代码块不是用于外部/一般用途的)。它们在控制命名空间污染方面也非常有用(在冗长的语言中,这是对自然复杂/长类的真正关注)。

But like anything, they can be open to abuse.

但和任何事情一样,它们也可能被滥用。

It is sad that C/C++ does not support such features as an standard. Most pascal variants and Ada do (almost all Algol-based languages do). Same with JavaScript. Same with modern languages like Scala. Same with venerable languages like Erlang, Lisp or Python.

令人遗憾的是,C/ c++不支持这样的特性作为标准。大多数pascal变体和Ada do(几乎所有基于algolde的语言都是这样做的)。相同的JavaScript。像Scala这样的现代语言也是如此。像Erlang、Lisp或Python之类的古老语言也是如此。

And just as with C/C++, unfortunately, Java (with which I earn most of my living) does not.

不幸的是,就像C/ c++一样,Java(我的大部分生活都是靠它维生的)也不是。

I mention Java here because I see several posters suggesting usage of classes and class' methods as alternatives to nested functions. And that's also the typical workaround in Java.

我在这里提到Java是因为我看到了一些海报,它们建议使用类和类的方法来替代嵌套函数。这也是Java中典型的解决方案。

Short answer: No.

简短的回答:没有。

Doing so tend to introduce artificial, needless complexity on a class hierarchy. With all things being equal, the ideal is to have a class hierarchy (and its encompassing namespaces and scopes) representing an actual domain as simple as possible.

这样做往往会在类层次结构中引入人为的、不必要的复杂性。在所有条件都相同的情况下,理想的方法是拥有一个类层次结构(及其包含的名称空间和范围),以尽可能简单地表示一个实际的域。

Nested functions help deal with "private", within-function complexity. Lacking those facilities, one should try to avoid propagating that "private" complexity out and into one's class model.

嵌套函数有助于处理“私有”、功能内部的复杂性。由于缺乏这些设施,我们应该尽量避免将“私有”的复杂性传播到一个人的类模型中。

In software (and in any engineering discipline), modeling is a matter of trade-offs. Thus, in real life, there will be justified exceptions to those rules (or rather guidelines). Proceed with care, though.

在软件(以及任何工程学科)中,建模是一个权衡取舍的问题。因此,在现实生活中,这些规则(或者更确切地说是指导方针)将有合理的例外。不过,谨慎行事。

#9


4  

All this tricks just look (more or less) as local functions, but they don't work like that. In a local function you can use local variables of it's super functions. It's kind of semi-globals. Non of these tricks can do that. The closest is the lambda trick from c++0x, but it's closure is bound in definition time, not the use time.

所有这些技巧看起来(或多或少)都是局部函数,但它们不是这样工作的。在局部函数中,可以使用它的超函数的局部变量。这是一种semi-globals。这些把戏都做不到。最接近的是c++0x的lambda技巧,但是它的闭包是在定义时间而不是使用时间内绑定的。

#10


3  

Let me post a solution here for C++03 that I consider the cleanest possible.*

我在这里发布一个c++ 03的解决方案,我认为它是最干净的

#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
    struct { RETURN_TYPE operator () FUNCTION } NAME;

...

int main(){
  DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
  demoLambda();

  DECLARE_LAMBDA(plus, int, (int i, int j){
    return i+j;
  });
  cout << "plus(1,2)=" << plus(1,2) << endl;
  return 0;
}

(*) in the C++ world using macros is never considered clean.

(*)在c++世界中,使用宏从来不被认为是干净的。

#11


3  

You can't have local functions in C++. However, C++11 has lambdas. Lambdas are basically variables that work like functions.

在c++中不能有本地函数。然而,C + + 11λ。lambda本质上是与函数类似的变量。

A lambda has the type std::function (actually that's not quite true, but in most cases you can suppose it is). To use this type, you need to #include <functional>. std::function is a template, taking as template argument the return type and the argument types, with the syntax std::function<ReturnType(ArgumentTypes). For example, std::function<int(std::string, float)> is a lambda returning an int and taking two arguments, one std::string and one float. The most common one is std::function<void()>, which returns nothing and takes no arguments.

lambda具有std:::function类型(实际上这不是完全正确的,但在大多数情况下您可以假定它是正确的)。要使用这种类型,您需要#include 。函数是一个模板,以返回类型和参数类型作为模板参数,语法std::function 是一个返回int并接受两个参数,一个std::string和一个float。最常见的是std::function ,它不返回任何东西,不接受任何参数。 ()> (argumenttypes)。例如,std::函数

Once a lambda is declared, it is called just like a normal function, using the syntax lambda(arguments).

一旦一个lambda被声明,它就会像一个普通函数一样被调用,使用语法lambda(参数)。

To define a lambda, use the syntax [captures](arguments){code} (there are other ways of doing it, but I won't mention them here). arguments is what arguments the lambda takes, and code is the code that should be run when the lambda is called. Usually you put [=] or [&] as captures. [=] means that you capture all variables in the scope in which the value is defined by value, which means that they will keep the value that they had when the lambda was declared. [&] means that you capture all variables in the scope by reference, which means that they will always have their current value, but if they are erased from memory the program will crash. Here are some examples:

要定义lambda,请使用语法[capture](参数){code}(还有其他方法,但这里不提)。参数是lambda使用的参数,而代码是在调用lambda时应该运行的代码。通常你把[=]或[&]作为捕获。[=]表示您捕获了值由值定义的范围内的所有变量,这意味着它们将保留声明lambda时的值。[&]意味着您通过引用捕获范围中的所有变量,这意味着它们将始终具有它们的当前值,但是如果从内存中删除它们,程序将崩溃。下面是一些例子:

#include <functional>
#include <iostream>

int main(){
    int x = 1;

    std::function<void()> lambda1 = [=](){
        std::cout << x << std::endl;
    };
    std::function<void()> lambda2 = [&](){
        std::cout << x << std::endl;
    };

    x = 2;
    lambda1();    //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
    lambda2();    //Prints 2 since that's the current value of x and x was captured by value with [&]

    std::function<void()> lambda3 = [](){}, lambda4 = [](){};    //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
                                                                 //[](){} is the empty lambda.

    {
        int y = 3;    //y will be deleted from the memory at the end of this scope
        lambda3 = [=](){
            std::cout << y << endl;
        };
        lambda4 = [&](){
            std::cout << y << endl;
        };
    }

    lambda3();    //Prints 3, since that's the value y had when it was captured

    lambda4();    //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
                  //This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
                  //This is why you should be careful when capturing by reference.

    return 0;
}

You can also capture specific variables by specifying their names. Just specifying their name will capture them by value, specifying their name with a & before will capture them by reference. For example, [=, &foo] will capture all variables by value except foo which will be captured by reference, and [&, foo] will capture all variables by reference except foo which will be captured by value. You can also capture only specific variables, for example [&foo] will capture foo by reference and will capture no other variables. You can also capture no variables at all by using []. If you try to use a variable in a lambda that you didn't capture, it won't compile. Here is an example:

您还可以通过指定它们的名称来捕获特定的变量。只需指定它们的名称,就可以按值捕获它们,使用& before指定它们的名称,就可以通过引用捕获它们。例如,[=,&foo]将按值捕获除foo外的所有变量,而[&,foo]将通过引用捕获除foo外的所有变量,而foo将被值捕获。您还可以只捕获特定的变量,例如[&foo]将根据引用捕获foo,并且不会捕获其他变量。您还可以使用[]来捕获所有变量。如果您试图在lambda中使用一个未捕获的变量,它将不会编译。这是一个例子:

#include <functional>

int main(){
    int x = 4, y = 5;

    std::function<void(int)> myLambda = [y](int z){
        int xSquare = x * x;    //Compiler error because x wasn't captured
        int ySquare = y * y;    //OK because y was captured
        int zSquare = z * z;    //OK because z is an argument of the lambda
    };

    return 0;
}

You can't change the value of a variable that was captured by value inside a lambda (variables captured by value have a const type inside the lambda). To do so, you need to capture the variable by reference. Here is an exampmle:

您不能更改lambda中值捕获的变量的值(值捕获的变量在lambda中具有const类型)。为此,需要根据引用捕获变量。这是一个exampmle:

#include <functional>

int main(){
    int x = 3, y = 5;
    std::function<void()> myLambda = [x, &y](){
        x = 2;    //Compiler error because x is captured by value and so it's of type const int inside the lambda
        y = 2;    //OK because y is captured by reference
    };
    x = 2;    //This is of course OK because we're not inside the lambda
    return 0;
}

Also, calling uninitialized lambdas is undefined behavior and will usually cause the program to crash. For example, never do this:

另外,调用未初始化的lambdas是一种未定义的行为,通常会导致程序崩溃。例如,千万不要这样做:

std::function<void()> lambda;
lambda();    //Undefined behavior because lambda is uninitialized

Examples

例子

Here is the code for what you wanted to do in your question using lambdas:

这里是你想用lambdas做的问题的代码:

#include <functional>    //Don't forget this, otherwise you won't be able to use the std::function type

int main(){
    std::function<void()> a = [](){
        // code
    }
    a();
    return 0;
}

Here is a more advanced example of a lambda:

这里有一个关于lambda的更高级的例子:

#include <functional>    //For std::function
#include <iostream>      //For std::cout

int main(){
    int x = 4;
    std::function<float(int)> divideByX = [x](int y){
        return (float)y / (float)x;    //x is a captured variable, y is an argument
    }
    std::cout << divideByX(3) << std::endl;    //Prints 0.75
    return 0;
}

#12


2  

But we can declare a function inside main():

但我们可以在main()中声明一个函数:

int main()
{
    void a();
}

Although the syntax is correct, sometimes it can lead to the "Most vexing parse":

虽然语法是正确的,但有时它会导致“最烦人的解析”:

#include <iostream>


struct U
{
    U() : val(0) {}
    U(int val) : val(val) {}

    int val;
};

struct V
{
    V(U a, U b)
    {
        std::cout << "V(" << a.val << ", " << b.val << ");\n";
    }
    ~V()
    {
        std::cout << "~V();\n";
    }
};

int main()
{
    int five = 5;
    V v(U(five), U());
}

=> no program output.

= >没有程序输出。

(Only Clang warning after compilation).

(编译后仅发出叮当警告)。

C++'s most vexing parse again

c++最烦人的解析再次出现