面试之快速学习c++11- 列表初始化和 lambda匿名函数的定义

这篇具有很好参考价值的文章主要介绍了面试之快速学习c++11- 列表初始化和 lambda匿名函数的定义。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习地址: http://c.biancheng.net/view/3730.html

8. C++11列表初始化(统一了初始化方式)

  1. 我们知道,在 C++98/03 中的对象初始化方法有很多种,请看下面的代码:
//初始化列表
int i_arr[3] = { 1, 2, 3 };  //普通数组
struct A1
{
    int x;
    struct B
    {
        int i;
        int j;
    } b;
} a = { 1, { 2, 3 } };  //POD类型: POD 类型即 plain old data 类型,简单来说,是可以直接使用 memcpy 复制的对象。

//拷贝初始化(copy-initialization)
int i = 0;
class Foo1
{
    public:
    Foo1(int) {}
} foo = 123;  //注意这里需要拷贝构造函数

//直接初始化(direct-initialization)
int j(0);
Foo1 bar(123);

2 .为了统一初始化方式,并且让初始化行为具有确定的效果,C++11 中提出了列表初始化(List-initialization)的概念。

3 . 在上面我们已经看到了,对于普通数组和 POD 类型,C++98/03 可以使用初始化列表(initializer list)进行初始化,但是这种初始化方式的适用性非常狭窄,只有上面提到的这两种数据类型可以使用初始化列表。

4 . 在 C++11 中,初始化列表的适用性被大大增加了。它现在可以用于任何类型对象的初始化,请看下面的代码。

class Foo2
{
public:
    Foo2(int) {}
private:
    Foo2(const Foo2 &);
    Foo2 operator=(const Foo2 &);
};

void testInitializer (){
    Foo2 a1(123);
    Foo2 a2 = 123;  //网站上面说 会报错error: 'Foo::Foo(const Foo &)' is private。但是我用xcode没有报错,断点进入到了Foo2(int) {}
    Foo2 a3 = {123};
    Foo2 a4{123};
    
}

5 . a3、a4 使用了新的初始化方式来初始化对象,效果如同 a1 的直接初始化, 这里需要注意的是,a3 虽然使用了等于号,但它仍然是列表初始化,因此,私有的拷贝构造并不会影响到它。

6 . 注意我把第一个构造函数改为 explicit Foo2(int) {}之后 a2, a3报错

7 . 如果真的要用初始化列表,那么最好用a4这种

8 . 另外,如同读者所想的那样,new 操作符等可以用圆括号进行初始化的地方,也可以使用初始化列表:


int* a1 = new int { 123 };
double b1 = double { 12.12 };
int* arr1 = new int[3] { 1, 2, 3 };

9 . 除了上面所述的内容之外,列表初始化还可以直接使用在函数的返回值上:

struct Foo3 {
    Foo3(int i, double j){}
};
Foo3 func3() {
    return {1, 3};

9. lambda匿名函数的定义

  1. 定义一个 lambda 匿名函数很简单,可以套用如下的语法格式:

[外部变量访问方式说明符] (参数) mutable noexcept/throw() -> 返回值类型 {
函数体; };

1) [外部变量方位方式说明符]
[ ] 方括号用于向编译器表明当前是一个 lambda 表达式,其不能被省略。在方括号内部,可以注明当前 lambda 函数的函数体中可以使用哪些“外部变量”。
所谓外部变量,指的是和当前 lambda 表达式位于同一作用域内的所有局部变量。

2) (参数)
和普通函数的定义一样,lambda 匿名函数也可以接收外部传递的多个参数。和普通函数不同的是,如果不需要传递参数,可以连同 () 小括号一起省略;

3) mutable
此关键字可以省略,如果使用则之前的 () 小括号将不能省略(参数个数可以为 0)。默认情况下,对于以值传递方式引入的外部变量,不允许在 lambda 表达式内部修改它们的值(可以理解为这部分变量都是 const 常量)。而如果想修改它们,就必须使用 mutable 关键字。
注意,对于以值传递方式引入的外部变量,lambda 表达式修改的是拷贝的那一份,并不会修改真正的外部变量;

4) noexcept/throw()
可以省略,如果使用,在之前的 () 小括号将不能省略(参数个数可以为 0)。默认情况下,lambda 函数的函数体中可以抛出任何类型的异常。而标注 noexcept 关键字,则表示函数体内不会抛出任何异常;使用 throw() 可以指定 lambda 函数内部可以抛出的异常类型。

值得一提的是,如果 lambda 函数标有 noexcept 而函数体内抛出了异常,又或者使用 throw() 限定了异常类型而函数体内抛出了非指定类型的异常,这些异常无法使用 try-catch 捕获,会导致程序执行失败(本节后续会给出实例)。

5) -> 返回值类型
指明 lambda 匿名函数的返回值类型。值得一提的是,如果 lambda 函数体内只有一个 return 语句,或者该函数返回 void,则编译器可以自行推断出返回值类型,此情况下可以直接省略-> 返回值类型。

6) 函数体
和普通函数一样,lambda 匿名函数包含的内部代码都放置在函数体中。该函数体内除了可以使用指定传递进来的参数之外,还可以使用指定的外部变量以及全局范围内的所有全局变量。

2 . ⚠️需要注意的是,外部变量会受到以值传递还是以引用传递方式引入的影响,而全局变量则不会。换句话说,在 lambda 表达式内可以使用任意一个全局变量,必要时还可以直接修改它们的值。

3 . 比如,如下就定义了一个最简单的 lambda 匿名函数:[]{}

4 . 外部变量格式 功能
[] 空方括号表示当前 lambda 匿名函数中不导入任何外部变量。
[=] 只有一个 = 等号,表示以值传递的方式导入所有外部变量;
[&] 只有一个 & 符号,表示以引用传递的方式导入所有外部变量;
[val1,val2,…] 表示以值传递的方式导入 val1、val2 等指定的外部变量,同时多个变量之间没有先后次序;
[&val1,&val2,…] 表示以引用传递的方式导入 val1、val2等指定的外部变量,多个变量之间没有前后次序;
[val,&val2,…] 以上 2 种方式还可以混合使用,变量之间没有前后次序。
[=,&val1,…] 表示除 val1 以引用传递的方式导入外,其它外部变量都以值传递的方式导入。
[this] 表示以值传递的方式导入当前的 this 指针。

5 . ⚠️注意,单个外部变量不允许以相同的传递方式导入多次。例如 [=,val1] 中,val1 先后被以值传递的方式导入了 2 次,这是非法的。文章来源地址https://www.toymoban.com/news/detail-639270.html


void testLambda() {
    int num[4]{2,5,3,4};
    sort(num, num+4, [num](int x, int y)->bool{return x < y;});
    cout<< "sort:" <<endl;
    for (auto &n: num) {
        cout<< n <<endl;
    }
}

到了这里,关于面试之快速学习c++11- 列表初始化和 lambda匿名函数的定义的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 初始化列表的使用

    问题 类中是否可以定义 const 成员? 可以的 下面的类定义是否合法? 如果合法,ci 的值是什么,存储在哪里? 上面的 Test 类定义是合法的,但是要定义 Test 类对象的时候,编译器会报错,提示 const 成员变量 ci 没初始化 类中的 const 成员 我们对上面的代码进行编译,编译直

    2024年02月09日
    浏览(56)
  • 初始化列表

     在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。 虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能成作初始化。因为 初始化只能进

    2024年02月04日
    浏览(57)
  • 【深度学习】 Python 和 NumPy 系列教程(三):Python容器:1、列表List详解(初始化、索引、切片、更新、删除、常用函数、拆包、遍历)

    目录 一、前言 二、实验环境 三、Python容器(Containers) 0、容器介绍 1、列表(List) 1. 初始化 a. 创建空列表 b. 使用现有元素初始化列表 c. 使用列表生成式 d. 复制列表 2. 索引和切片 a. 索引 b. 负数索引 c. 切片 3. 常用操作(更新、删除) a. 更新单个元素 b. 更新切片 c. 删除单

    2024年02月09日
    浏览(53)
  • C++之初始化列表详细剖析

    初始化列表:以一个 冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个 \\\"成员变量\\\" 后面跟一个 放在括号中的初始值或表达式。 不知道大家有没有想过这样一个问题,成员函数明明可以在函数内部对成员变量进行赋值,那为什么还要搞出初始化列表这个东西呢?这个

    2024年02月06日
    浏览(57)
  • C++ | 谈谈构造函数的初始化列表

    我们知道,对于下面这个类A的成员变量 _a1 和 _a2 属于【声明】,还没有在内存中为其开辟出一块空间以供存放,真正开出空间则是在【定义】的时候,那何时定义呢?也就是使用这个类A去实例化出对象的时候 这个对象的空间被开出来了,难道里面的成员变量就一定开出空间

    2023年04月11日
    浏览(100)
  • 【C++奇遇记】构造函数 | 初始化列表

    🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集 数据库专栏 初阶数据结构 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📆 未来很长,值得我们全力奔赴更美好的生活✨ 🐤本篇文章将讲授C++的初始化列表相关的知识

    2024年02月12日
    浏览(57)
  • C++中包含初始化列表的构造函数

    构造函数对初始化成员变化很有用。另一种初始化成员的方式是使用初始化列表。对于程序中接受两个参数的构造函数,其包含初始化列表的变种类似于下面这样: 格式为: :成员变量1(参数1),成员变量2(参数2) 编译器会将初始化列表一一转换成代码,并将这些代码放

    2024年02月05日
    浏览(55)
  • C++:初始化列表,static成员,友元,内部类

    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C++》 本篇博客作为C++:初始化列表,static成员,友元,内部类的知识总结。 初始化列表:以冒号开始,接着是一个以逗号分隔的数据成员列表,每个“成员变量”后面跟一个放在括号中的初始值或表达式。 初始化

    2024年02月07日
    浏览(56)
  • 【C++】构造函数和初始化列表的性能差距

    构造函数和初始化列表的性能差距对比测试 在C++类和对象中,你可能听到过更加推荐用初始化列表来初始化类内成员。如果类内成员是自定义类型,则只能在初始化列表中调用自定义类型的构造函数。 但初始化列表和在构造函数体内直接赋值有无性能差距呢?今天就用一份

    2024年02月11日
    浏览(44)
  • 【C++】初始化列表构造函数VS普通构造函数

    初始化列表构造函数最优先匹配问题 对于一个类而言,只要其中包含有初始化列表的构造函数,编译器在编译使用{}语法的构造时会最倾向于调用初始化列表构造函数,哪怕做类型转换也在所不惜,哪怕有类型最佳匹配的普通构造函数或移动构造函数也会被劫持 编译器这种热

    2024年02月05日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包