Parentheses at the end of a C++11 lambda expressio

2019-02-15 06:03发布

问题:

I am confused with some of the examples that I have come across with C++11 lambdas. For eg:

#include <iostream>
#include <string>

using namespace std;

int main()
{ 
        cout << []()->string{return "Hello World 1!";}() << endl;

        []{cout << "Hello World 2!" << endl;}();

        string result = [](const string& str)->string {return "Hello World " + str;}("2!");
        cout << "Result: " << result << endl;

        result = [](const string& str){return "Hello World " + str;}("3!");
        cout << "Result: " << result << endl;

        string s;
        [&s](){s = "Hello World 4!";};   // does not work
        cout << s << endl; 
        [&s](){s = "Hello World 4!";}(); // works!
        cout << s << endl;

        return 0;
}

I am unable to figure out what the parentheses at the end are doing. Are they instantiating, as a constructor, a lambda? Given that the template for a lambda is:

[capture_block](parameters) mutable exception_specification -> return_type {body}

it baffles me that those parentheses are required for those instances to work. Can someone explain what they are why they are required?

回答1:

Well, given that a lambda expression is basically an anonymous function, the parentheses at the end do nothing more than just call this function. So

result = [](const string& str){return "Hello World " + str;}("3!");

is just equivalent to

auto lambda = [](const string& str){return "Hello World " + str;};
string result = lambda("3!");

This holds in the same way for a lambda with no arguments, like in

cout << []()->string{return "Hello World 1!";}() << endl;

which would otherwise (if not called) try to output a lambda expression, which in itself doesn't work. By calling it it just puts out the resulting std::string.



回答2:

They're calling the function object!

In two phases:

auto l = []()->string{return "Hello World 1!";}; // make a named object
l(); // call it

A lambda expression evaluates to a function object. Since there's no operator<< overload that takes such a function object, you'd get an error if you didn't call it to produce a std::string.