码迷,mamicode.com
首页 > 其他好文 > 详细

Lambda 表达式语法

时间:2014-05-26 07:32:04      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:des   style   class   c   blog   code   

本主题介绍 lambda 表达式的语法。 它演示提供 lambda 表达式的结构元素的示例,这些元素与示例。

Lambda 表达式语法

lambda expression (items marked with the opt subscript are optional):‘ data-guid="7c06475b6c7e659231eab3f6a09da2c5">下面用于定义显示语法,ISO C++11 从标准,lambda 表达式 (项标记下标 选择 是可选的):

        lambda-introducer lambda-declaratoroptcompound-statement‘ data-guid="da567d9b01ffc90b2f806d6102b02c8a"> lambda-introducer lambda-declarator 选择 compound-statement

进一步失败的组件这些语法如下:

lambda-introducer: 
        [lambda-captureopt]‘ data-guid="e4c05141edef0d183536397ad2313d5b"> [ lambda-capture 选择 ] 
lambda-capture:
        capture-default
        capture-list
        capture-default,capture-list‘ data-guid="ded357489ff523ebac123eeea9f8e5b9"> capture-default , capture-list 
capture-default:
        &
        =
capture-list:
        capture ...opt‘ data-guid="7fc7bb76894402a3f57acea82c41a6c9"> capture ... 选择 
        capture-list,capture ...opt‘ data-guid="907b62c7b64c05e8dc0e3f9538d728e4"> capture-list , capture ... opt 
capture:
        identifier
        &identifier‘ data-guid="7feb2bf421ffc991f9d142012cdc8a6e"> & identifier 
        this
lambda-declarator:
        (parameter-declaration-clause)mutableopt‘ data-guid="99306ee62067d0154f8608c670fd2325"> ( parameter-declaration-clause ) mutable 选择 
                exception-specificationoptattribute-specifier-seqopttrailing-return-typeopt‘ data-guid="c5b4a2734548c72609a9e160f562296d"> exception-specification 选择 attribute-specifier-seq 选择 trailing-return-type 选择 

Visual Studio 支持 C++11 标准 Lambda 表达式语法及其所有 C++11 功能与除了 lambda,以下操作:

  • 要,任何其他类,不会自动生成的构造函数并将不根据标准要求将赋值运算符。 Rvalue References section of Support For C++11 Features (Modern C++).‘ data-guid="1f15aa4e6b46f9f25fa58ab28a364497">有关 rvalue 引用行为支持的更多信息,请参见 对 C++11 功能的支持(现代 C++)中的 Rvalue References 节。

  • attribute-specifier-seq is not yet supported.‘ data-guid="105a6431ee4e5f929e7a14b7486a6ae8">可选的 attribute-specifier-seq 不支持。

Visual Studio 向 C++11 lambda 功能通过添加以下功能:

    • 无状态是 lambda omni 转换的任意函数使用调用约定的函数的指针。

    • { return expression; } as long as all return statements have the same type. (This is now in the proposed C++14 Standard.)‘ data-guid="c4be162dba4357621396c005aa9f91ab">比 { return expression; } 复杂的主体的 lambda 自动返回这样的类型,只要所有返回语句具有相同的类型。(这在 C++14 标准现在建议的)。

Lambda 表达式的属性

下图将该语法映射到示例。

bubuko.com,布布扣

图中的标注如下所示:

  1. lambda-introducer (referred to as capture clause later in this topic)‘ data-guid="230e892924e79481c72a4e79d3ef8021">lambda-introducer(在本主题的后面称为“capture 子句”)

  2. lambda declarator (referred to as parameter list later in this topic)‘ data-guid="f7132131cadfe2fae3609f17053090bd">lambda declarator(在本主题的后面称为“参数列表”)

  3. mutable (referred to as mutable specification later in this topic)‘ data-guid="5948943488e9ef1abebb45c43b50debf">mutable(在本主题的后面称为“可变规范”)

  4. exception-specification (referred to as exception specification later in this topic)‘ data-guid="f1d1f05ee188f2edd9f9a14bff636d23">exception-specification(在本主题的后面称为“异常规范”)

  5. trailing-return-type (referred to as return type later in this topic)‘ data-guid="f4000e6e2709000c8f72714c0ecc46ad">trailing-return-type(在本主题的后面称为“返回类型”)

  6. compound-statement (referred to as lambda body later in this topic)‘ data-guid="281c9b34dbcf1da68852dab92d14c081">compound-statement(在本主题的后面称为“lambda 体”)

以下各节对该语法进行了更详细的说明。

Capture 子句

lambda 表达式是类、构造和函数调用运算符。 如同,在定义类时,决定需要发生的对象捕获变量不受值还是引用或者是否是必需的。 captured.‘ data-guid="6c33afef79a40306c474574370f5d5d3">如果 lambda 表达式需要访问局部变量和函数参数,它们需要 捕获。 lambda-introducer in the syntax) specifies whether the body of the lambda expression can access variables in the enclosing scope by value or by reference: Variables that have the ampersand (&) prefix are accessed by reference and variables that do not have the & prefix are accessed by value.‘ data-guid="c40c2b1e1b09d1b6c817849b8f6620a7">get 子句 (语法中的lambda-introducer ) 所指定 lambda 表达式的主体是可以访问在封闭范围内的变量通过值或通过引用:包含" &的变量 (&) 为前缀) 没有 & 前缀的引用和变量访问值由访问。

[ ], indicates that the body of the lambda expression accesses no variables in the enclosing scope.‘ data-guid="63675b2a3256576c874023b197bac1c0">空 capture 子句 [ ] 指示 lambda 表达式的主体不访问封闭范围中的变量。

捕获默认模式指定您未显式指定的获取变量是否捕获通过值或通过引用,如果使用它们。 capture-default in the syntax) by specifying & or = as the first element of the capture clause.‘ data-guid="06ca7cba6d4564676c3248770ee0e3f1">您可以通过将 & 或 = 指定为 capture 子句的第一个元素来指定默认捕获模式(语法中的 capture-default)。 & element specifies that the body of the lambda expression accesses all captured variables by reference unless you explicitly specify otherwise.‘ data-guid="e1b847322b78a606bba9d77c52fe04be">& 元素指定 lambda 表达式的主体通过引用访问所有捕获的变量,除非您显式地另行指定。 = element specifies that the body of the lambda expression accesses all captured variables by value unless you explicitly specify otherwise.‘ data-guid="ee082ebeb43766571328678d7d2f24fe">= 元素指定 lambda 表达式的主体通过值访问所有捕获的变量,除非您显式地另行指定。 total by reference and the external variable factor by value, then the following capture clauses are equivalent:‘ data-guid="5bad063af18403fe3f4e25e148c3651f">例如,如果 lambda 表达式的主体通过引用访问外部变量 total 并通过值访问外部变量 factor,那么以下 capture 子句等效:

[&total, factor]
{factor, &total]
[&, factor]
[factor, &]
[=, &total]
[&total, =]

capture-default is that all variables in the scope are captured whether they are used in the lambda or not.‘ data-guid="b08db9512b44b311fa2f9cc31c0b2a9e">有关使用 capture-default 的一种常见的误会位于范围内的任何变量捕获是否使用 lambda。 capture-default.‘ data-guid="cc904375d879668befe499b0b9a84de0">事实上并非如此 - 在 lambda 提到的那些变量捕获,则使用 capture-default

如果捕获子句包括 capture-default&,该 lambda 的 get 子句 capture 的 identifier 不能由 & capture-default (=), each capture of that capture clause must be in the form & identifier.‘ data-guid="1cb38aa3342faf3177ce98fff2e74c79">沿着同一行,因此,如果获取子句包括 capture-default (=),该子句获得每个 capture 必须以窗体 & identifier。 this cannot appear more than once in a capture clause.‘ data-guid="cf4debaa20847e79b392630c6e1a44b3">标识符或 this 不能多次出现在子句获得。 下面的代码段阐释了一些示例。

bubuko.com,布布扣
struct S { void f(int i); };

void S::f(int i) {
    [&, i]{};    // OK
    [&, &i]{};   // ERROR: i preceded by & when & is the default
    [=, this]{}; // ERROR: this when = is the default
    [i, i]{};    // ERROR: i repeated
}
bubuko.com,布布扣

省略号 capture 后跟是 pack 扩展,以下面的示例:variadic 模板

template<class... Args>
void f(Args... args) {
    auto x = [args...] { return g(args...); };
    x();
}

可以将 lambda 表达式用于类方法的主体中。 this pointer to the capture clause to provide access to the methods and data members of the enclosing class.‘ data-guid="8d00bf9c4599b0608293c600ef7b1a2c">将 this 指针传递到 capture 子句以提供对封闭类的方法和数据成员的访问权限。 Examples of Lambda Expressions.‘ data-guid="c858eb99637a672271f25aae1cec6179">有关示例演示如何使用类用方法的 lambda 表达式,请参见示例:使用将方法的 Lambda 表达式。主题 Lambda 表达式的示例

在使用子句获得时,应记住这些,理解和压力,尤其当使用具有多线程时的 lambda:

  • 引用获取可用于修改变量之外,获取值,而无法用于修改变量之外 (变量允许复制修改,从原始的)。

  • 而值获取不会反映更新给变量,则获取引用会反映更新到变量中。

  • 而值获取没有生存期依赖关系,这些依赖关系的引用,获取引入生存期依赖关系,这些依赖关系。

许多这些点在这和相关文章中的代码示例所示。

参数列表

lambda declarator) for a lambda expression is optional and resembles the parameter list for a function.‘ data-guid="63f201d4283b35f483995264d43f8d72">参数列表 (lambda declarator) lambda 表达式中为选项并类似于函数的参数列表。

lambda 表达式可以将另一个 lambda 表达式作为其参数。 Examples of Lambda Expressions.‘ data-guid="5de864549207e726053ee89acb16218d">有关详细信息,请参阅主题 Lambda 表达式的示例中的“高阶 Lambda 表达式”。

lambda 表达式的参数列表可以是可选的。 lambda-declarator: does not contain exception-specification, trailing-return-type, or mutable.‘ data-guid="bb965b1339c1e3ea4048508edca1123a">可以省略空括号,如果不传递参数到 lambda 表达式,并且 lambda-declarator: 不包含 exception-specificationtrailing-return-typemutable

可变规范

通常的 lambda 函数调用运算符为 Const 按值,但是,mutable 可以取消此操作。 它不导致变量的数据成员。 可变规范使用 lambda 表达式的主体修改由捕获值的变量。 mutable keyword.‘ data-guid="081cbf492611ee14dd8055b696cf8c29">某些示例本文后面演示了 mutable 关键字的用法。

异常规范

throw() exception specification to indicate that the lambda expression does not throw any exceptions.‘ data-guid="864feb25d624512223eac67ca5e65a0d">您可以使用 throw() 异常规范来指示 lambda 表达式不会引发任何异常。 C4297 if a lambda expression declares the throw() exception specification and the lambda body throws an exception, as shown in the following example:‘ data-guid="51492dd90d3455655471188842c736ef">与正则函数一样,如果 lambda 表达式声明 throw() 异常规范且 lambda 体引发异常,Visual C++ 编译器将生成警告 C4297,如以下示例所示:

// throw_lambda_expression.cpp
// compile with: /W4 /EHsc 
int main() // C4297 expected
{
   []() throw() { throw 5; }();
}

返回类型

auto keyword unless a trailing-return-type is specified.‘ data-guid="c38d414de342a6f2033ff784ef760918">lambda 表达式的返回类型自动推断,并且,这发生,而无需添加关键字,除非指定 trailing-return-typeauto trailing-return-type resembles the return type part of an ordinary method or function.‘ data-guid="c2fa50eaa88f4b294a0827a5d39305b0">trailing-return-type 类似于普通方法或函数返回类型的部件。 -&gt; before the return type.‘ data-guid="f32cc4800f78ae0b4a707e2f4b348df9">但是,遵循返回类型参数列表,您必须包括尾部的返回类型关键字 ->,在返回类型。

如果 lambda 体包含单个返回语句或 lambda 表达式不返回值,则可以省略 lambda 表达式的返回类型部分。 如果 lambda 体包含单个返回语句,编译器将从返回表达式的类型推导返回类型。 void.‘ data-guid="dbcad1a80c2671c1e63e83dbb889d62b">否则,编译器会将返回类型推导为 void(可能需要显示指明返回类型)。 考虑阐释此原则下面的示例代码段。

auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return{ 1, 2 }; };  // ERROR: return type is void, deducing 
                                  // return type from braced-init-list not valid

lambda 表达式可以生成另一个 lambda 表达式作为其返回值。 Examples of Lambda Expressions.‘ data-guid="5de864549207e726053ee89acb16218d">有关详细信息,请参阅主题 Lambda 表达式的示例中的“高阶 Lambda 表达式”。

Lambda 体

compound-statement) part of a lambda expression can contain anything that the body of an ordinary method or function can contain.‘ data-guid="f6f7711b58566f4e0ba3338648808408">lambda 表达式主体的 lambda (compound-statement) 中可以包含一般的方法或函数主体所能包含的所有内容。 普通函数和 lambda 表达式的主体均可访问以下变量类型:

  • 参数

  • 本地声明变量

  • this is captured)‘ data-guid="061c2060e88df49524cd1ca88ab3cd19">类数据成员 (在声明类和 this 内捕获)

  • 具有静态存储持续时间的任何变量(例如,全局变量)

此外,lambda 表达式可以访问它从封闭范围中捕获的变量。 explicitly captured if it appears in the capture clause of the lambda expression.‘ data-guid="4b80d2b6a52c7399c0814480cbe56ad4">如果某个变量显示在 lambda 表达式的 capture 子句中,则该变量是显式捕获的。 implicitly captured.‘ data-guid="452895ab9d3dc569058e37c3da341035">否则,该变量是隐式捕获的。 lambda 表达式的主体使用默认捕获模式来访问隐式捕获的变量。

n by value and implicitly captures the variable m by reference:‘ data-guid="2fa2baef7118434466b3bf796a5f9c70">以下示例包含通过值显式捕获变量 n 并通过引用隐式捕获变量 m 的 lambda 表达式:

bubuko.com,布布扣
// captures_lambda_expression.cpp
// compile with: /W4 /EHsc 
#include <iostream>
using namespace std;

int main()
{
   int m = 0;
   int n = 0;
   [&, n] (int a) mutable { m = ++n + a; }(4);
   cout << m << endl << n << endl;
}
bubuko.com,布布扣

本示例将以下内容输出到控制台:

5
0

n is captured by value, its value remains 0 after the call to the lambda expression.‘ data-guid="cd5a3531d8a41f6e44e7be185f221c83">由于变量 n 是通过值捕获的,因此在调用 lambda 表达式后,变量的值仍保持 0 不变。 mutable specification allows n to be modified within the lambda.‘ data-guid="2b5ab9c1f809320dd5702b305da46788">指定 mutable 允许 n 是在 lambda 中修改。

尽管 lambda 表达式只能捕获具有自动存储持续时间的变量,但您可以在 lambda 表达式的主体中使用具有静态存储持续时间的变量。 以下示例使用 generate 函数和 lambda 表达式为 vector 对象中的每个元素赋值。 lambda 表达式将修改静态变量以生成下一个元素的值。

bubuko.com,布布扣
void fillVector(vector<int>& v)
{
    // A local static variable.
    static int nextValue = 1;

    // The lambda expression that appears in the following call to
    // the generate function modifies and uses the local static 
    // variable nextValue.
    generate(v.begin(), v.end(), [] { return nextValue++; }); 
    //WARNING: this is not thread-safe and is shown for illustration only
}
bubuko.com,布布扣

generate function, see generate. ‘ data-guid="d7921455d70fff4b583ab6a110d1cabf">有关 generate 函数的详细信息,请参阅 生成

下面的代码示例使用从前面的函数,并将该表达式的 lambda 表达式的示例与 STL generate_n的算法。 该 lambda 表达式分配的 vector 对象的元素。前两个元素的和的。 mutable keyword is used so that the body of the lambda expression can modify its copies of the external variables x and y, which the lambda expression captures by value.‘ data-guid="08d948f43c776a52ea7576cf6e11a107">改用 mutable 关键字,这样 lambda 表达式体才能改变其外部变量 x 和 y的复制,lambda 表达式按值捕获。 x and y by value, their values remain 1 after the lambda executes.‘ data-guid="79c37a26742c33aa9f3aff17d10e8cc7">由于 lambda 表达式按值捕获原始变量 x 和 y,它们的值保持为 1,在 lambda 后执行。

bubuko.com,布布扣
// compile with: /W4 /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

using namespace std;

template <typename C> void print(const string& s, const C& c) {
    cout << s;

    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

void fillVector(vector<int>& v)
{
    // A local static variable.
    static int nextValue = 1;

    // The lambda expression that appears in the following call to
    // the generate function modifies and uses the local static 
    // variable nextValue.
    generate(v.begin(), v.end(), [] { return nextValue++; });
    //WARNING: this is not thread-safe and is shown for illustration only
}

int main()
{
    // The number of elements in the vector.
    const int elementCount = 9;

    // Create a vector object with each element set to 1.
    vector<int> v(elementCount, 1);

    // These variables hold the previous two elements of the vector.
    int x = 1;
    int y = 1;

    // Sets each element in the vector to the sum of the 
    // previous two elements.
    generate_n(v.begin() + 2,
        elementCount - 2,
        [=]() mutable throw() -> int { // lambda is the 3rd parameter
        // Generate current value.
        int n = x + y;
        // Update previous two values.
        x = y;
        y = n;
        return n;
    });
    print("vector v after call to generate_n() with lambda: ", v);

    // Print the local variables x and y.
    // The values of x and y hold their initial values because 
    // they are captured by value.
    cout << "x: " << x << " y: " << y << endl;

    // Fill the vector with a sequence of numbers
    fillVector(v);
    print("vector v after 1st call to fillVector(): ", v);
    // Fill the vector with the next sequence of numbers
    fillVector(v);
    print("vector v after 2nd call to fillVector(): ", v);
}
bubuko.com,布布扣
vector v after call to generate_n() with lambda: 1 1 2 3 5 8 13 21 34
x: 1 y: 1
vector v after 1st call to fillVector(): 1 2 3 4 5 6 7 8 9
vector v after 2nd call to fillVector(): 10 11 12 13 14 15 16 17 18

 




Lambda 表达式语法,布布扣,bubuko.com

Lambda 表达式语法

标签:des   style   class   c   blog   code   

原文地址:http://www.cnblogs.com/wuchanming/p/3747886.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!