首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C++编程经验(12):C++11新特性

C++编程经验(11):std::function 和 bind绑定器,虽然在这一篇里面专门讲过了,但是感觉有点抽象,重新捋一下,不然也不长记性呐。...---- lambda表达式 简单来说,Lambda函数也就是一个函数,的语法定义如下: [capture](parameters) mutable ->return-type{statement}...内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。 与普通函数最大的区别是,除了可以使用参数以外,Lambda函数还可以通过捕获列表访问一些上下文中的数据。...---- using 现在不仅仅可以用它引用名空间了,不过现在也不怎么用这个引用名空间了,都是用域作用符::。...一旦线程执行完毕,它所分配的资源将会被释放

94520
您找到你想要的搜索结果了吗?
是的
没有找到

C++代码简化之道

3. lambda表达式替换手写函数和函数对象 lambda表达式(或者说lamba对象)可能是C++程序员在回答『熟悉C++11?』这个问题,答完auto之后,说出的第二个新语法。...你就可以理解成是lambda的引用捕获功能。 在lambda的参数之外,获取到了其他的参数。并且是可跨越lambda生命周期的。...唯一需要注意的是:引用捕获可能在后续lambda对象被实际调用的时候,出现引用悬空(类似空指针),从而出现core dump。 4....但是如果顺序逻辑太多。那么要抽成很多个函数,而且每个函数内只有寥寥几行代码。反而啰嗦。 其二:使用异常。如果是Java语言应该很习惯用异常来实现这个逻辑,把顺序逻辑封在 try catch块里。...但曾经在C++98的环境下工作时,还是很少见到这种直接返回对象的写法。其实不是所有返回对象函数定义都能触发RVO,如果不清楚,C++98的程序员还是谨慎使用。 但是C++11开始,你不用担心了。

1.2K20

推荐使用C++ 11

move语义通过除了复制操作外还允许你有一个move构造函数(move constructor)和一个move赋值运算(move assignment)符提供这个机制。 你知道?...理由5:Lambda表达式提供了一种方法定义匿名方法对象(实际上是闭包),这是代码更加线性和有规律可循。...t.fuel_level() > _min_fuel_level; }); } // 何问起 hovertree.com 理由6:新的智能指针(smart pointer)替换了有问题的auto_ptr,你可以不用担心内存的释放并移除相关释放内存的代码了...C++的std::function提供了这方面的功能。方法提供一种包装和传递任何可调用的东西-函数指针, 仿函数(functor), lambda表达式等。...如果你的错误在运行时发生,这意味着你至少需要运行软件,并可能得通过一系列步骤重现错误,这需要时间。 C++ 11提供了一种方法检查先决条件并尽早的在可能的时机捕获错误-编译过程中,在你运行代码前。

47420

每个开发者都应该了解的一些C++特性

仍然是被广泛使用的最难编程语言之一。但是相比于之前的版本,确实对用户更加友好了。 今天,我们深入发掘一下每位开发者都应该了解的新特性(这些新特性从 C++11 时开始出现,距今已有八年历史了)。...记住,当使用 auto 时,必须确保你的编译器可以通过某种方式推断数据类型。 现在问题来了,如果写 auto a = {1, 2, 3} 会发生什么?会有编译错误?这是向量?...实际上,C++11 引入了 std::initializer_list,如果声明为 auto,那么初始化列表会被认为是这种轻量级容器。...因此,如果你想在 lambda 函数中将数据转换成其他形式,你可以像下面这段代码一样,利用作用域来使用 lambda。 ?...因此如果某些操作可以让编译器做,就可以减轻运行时的负担,从而提高时间效率。 ? 上面的代码是 constexpr 的一个常见例子。

73320

重温 CC++ 笔记

个人认为,在掌握了专栏里 C++11/14 知识的基础上,如果再面对一个 C++ 新的语言特性,你不能够在五分钟(或者再略长一点)的时间里理解的含义和作用,就说明里面的“坑”很深。...,如果真的有异常发生,请让死得干脆点,直接崩溃(crash、core dump)。”...也可以明确指定变量名和捕获方式 参数使用 auto 声明,可以让 lambda 表达式处理不同类型的参数: //5.泛型的 lambda void test_lambda_3() { //参数使用 auto...你更应该去关注的参与者、设计意图、面对的问题、应用的场合、后续的效果等代码之外的部分,它们通常比实现代码更重要。...简单、安全 在使用 lambda 表达式的时候,要特别注意捕获变量的生命周期,如果是在线程里异步执行,应当尽量用智能指针的【值】捕获,虽然有点麻烦,但比较安全 5.搭建 http 服务 介绍及Windows

1.2K30

C++11-lambda表达式包装器线程库

C++11篇三 零、前言 一、lambda表达式 1、lambda的引入 2、lambda表达式语法 3、捕获列表说明 4、函数对象与lambda表达式 二、包装器 1、function包装器 2、bind...,编译器根据[]判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用 (parameters): 参数列表,与普通函数的参数列表一致,如果不需要参数传递,...表达式实际上可以理解为无名函数,该函数无法直接调用,如果想要直接调用,可借助auto将其赋值给一个变量 3、捕获列表说明 概念: 捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用...)时可能会发生以下三种情况: 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉...如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock) std::recursive_mutex 其允许同一个线程对互斥量多次上锁(即递归上锁),获得对互斥量对象的多层所有权,释放互斥量时需要调用与该锁层次深度相同次数的

1.1K30

Modern c++快速浅析

int arr[pFunc(100)]; 捕获生命周期 C++中其实并没有闭包的概念,更准确的应该lambda划分为带捕获lambda以及不带捕获lambda 在C#这种具备GC机制的语言中,闭包能够延长捕获的变量的生命周期...(理解为能够延长生命周期的按引用捕获) 而C++中的按引用捕获并不能延长对象的生命周期,且按引用捕获会导致lambda表达式包含了对局部对象的引用,这很可能会导致空悬引用 std::function<void...); 除了“移动捕获”外,还可以利用初始化捕获初始化Lambda表达式中所需要使用的变量 auto lambda = [uniquePtr = std::make_unique()]() {...<< std::endl; }; } }; 如果捕获的是*this,那么Lambda会存在这整个类的副本,一切访问和修改都是发生在这个副本上的 struct My_Struct { int data...•如果使用捕获,函数体中是否有使用捕获的变量 struct My_Struct { private: int data = 20; double pi = 3.14; public:

14010

Effective Modern C++翻译(6)-条款5:auto比显示的类型声明要更好

这一章包括了auto的细则 条款5:auto比显示的类型声明要更好 这是一个看起来非常简单的例子 int x; 等一下,该死,忘记初始化x了,所以的值是不确定的,也许它被初始化为0了,不过这要取决于的上下文...哦,之前说过C++很有趣真的说过? 现在让我们声明一个局部变量,这个变量的类型是一个闭关的类型,但是这个闭包的类型只有编译器才能知道,你可以写出?...34,,我会尽最大的努力让你使用lambdas替代std::bind)( A similar argument can be made for auto over std::function...最后的两个例子,当应该使用std::vector::size_type时使用了unsigned和应该使用std::pair时使用std::pair...,证明了显示的类型声明有时候会导致一些你不希望的隐式的类型转换,而如果使用auto声明目标变量,你就不必担心想要声明的变量和对应的初始化式间的类型不匹配问题了。

859100

C++11的简单介绍(下)

_evaluate; }); } 上述代码就是使用C++11中的lambda表达式解决,可以看出lambda表达式实际是一个匿名函数。...在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。 注意: 在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。...其实lambda函数就和仿函数差不多,在编译器中它会被认为是一个仿函数对象! 2. 捕获列表说明 捕捉列表描述了上下文中哪些数据可以被lambda使用,以及使用的方式传值还是传引用。...,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock...) std::recursive_mutex 其允许同一个线程对互斥量多次上锁(即递归上锁),获得对互斥量对象的多层所有权,释放互斥量时需要调用与该锁层次深度相同次数的 unlock(),除此之外,

7110

每个C++开发者都应该学习和使用的C++11特性

本文讨论了所有开发人员都应该学习和使用的一系列 C++11特性。该语言和标准库中有很多新增功能,本文只是触及了皮毛。但是,相信其中一些新功能应该成为所有C++开发人员的日常工作。...unsetunset7、匿名函数unsetunset Lambda表达式是C++11引入的一种新的语法特性,用于创建匿名函数,提供了一种更加灵活和方便的方式编写内联的函数对象。...可以按值捕获、按引用捕获,也可以使用&表示按引用捕获、=表示按值捕获。 parameter list:参数列表,与普通函数的参数列表类似。...以下是一些示例: Lambda表达式不捕获任何外部变量,且不带参数和返回类型: [] { std::cout << "Hello, Lambda!"...使用范围-based for 循环: 在 C++11 中,我们还可以使用范围-based for 循环遍历容器,自动使用 begin() 和 end() 函数获取容器的迭代器。

4610

【笔记】C++2.0新特性

: lambda是C++11新加入的闭包语法, 一个lambda对象的实际类型我们一般写不出来, 如果想要在后面使用lambda对象的话常常需要用到decltype, 且lambda本身也常常用到decltype...最基础的lambda展开后形如下面的样子: // 如果我们写出下面的lambda, 会被展开为下面的形式 [x](int k){ std::cout<<k; }; // 展开的函数对象是匿名的, 其名称由编译器生成...这就是为什么我们不允许改变捕获的变量的值 void operator()(int k) const { std::cout<<k; } }; 复杂点的lambda展开后是下面的样子: // 这里对..., 只是马上就会被丢弃而已, 如果不加以利用就很浪费, 例如我们在赋值语句使用函数的返回值(右值)需要对对象进行两次构造....尽管这里都是左值, 但是它们的声明类型依然是正确的, 我们想到可以利用转型恢复的引用属性 为了适配模板, 我们可以写出如下的模板函数. pass传入ref的参数只有int&和int&&两种类型, 且都是左值

85620

lambda表达式的高阶用法

真的是是这样?...加以声明 //这样的对象在 lambda使用,但是他们不能被捕获 //但是使用了默认值捕获模式,会给人一种错觉,认为他们可以被捕获 void addDivisorFilter1()//运行结果怀疑怀疑了下面说法...都会被递增,从而把好多lambda添加到 filters时每个lambda的行为不一样 * 对应于 divisor的薪值,从实际效果来看是按引用捕获 divisor *...* 含义是: * 在闭包中创建一个成员变量pw,然后使用针对局部变量 pw实施std::move得结果初始化该成员变量 * * 如果auto pw 没被修改...*/ //情况4: //复杂处理 更加凸显 lambda的好处 //lambda的处理 //[] 如果捕获全局变量的话,不用加 = 或者 & //但是 [] 如果捕获局部变量的话 必须加 = 或者 &

1.3K20

C++11 在析构函数中执行lambda表达式(std::function)捕获this指针的陷阱

想说的是善用lambda表达式,将给C++编程带来极大的便利,这是本人最近学习C++11以来真实深切的感受,但是有时候误用lambda表达式也会给编程带来极大的隐患,本文以最近的经历说明lambda表达式在使用上的一例陷阱...std::function对象已经被析构清除了,这时fun已经是个无效变量,执行当然会抛出异常。...解决问题 解决这个问题的办法很多种, 总的原则就是:如果要在析构函数中调用lambda表达,就要避免lambda使用类成员变量, 对于这个例子,最简单的办法就是修改test_lambda构造函数...同样用前面在std::function析构函数加断点的方式在eclipse+gcc环境下做了测试,测试结果表明gcc也是按C++标准顺序执行对象析构的,但不同的是gcc在构造下面这个lambda表达式时...总结 如果在基类的析构函数中执行子类提供lambda表达式,lambda表达式中要避免使用子类中类成员变量。

1.4K10

C++11新特性学习笔记

但是,如果程序员为类显式的自定义了非默认构造函数,编译器将不再会为隐式地生成默认无参构造函数。...::move 既然编译器只对右值引用才能调用转移构造函数和转移赋值函数,而所有命名对象都只能是左值引用,如果已知一个命名对象不再被使用而想对调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用...可以对动态资源进行管理,保证任何情况下,已构造的对象最终会销毁,即的析构函数最终会被调用。...int main() { //使用std::functionstd::bind存储和操作lambda表达式 function f1 = [](int a) { return...这个过程有点类似于,公司部门里,使用着打印机打印东西的同时(还没有打印完),别人刚好也在此刻使用打印机打印东西,如果不做任何处理的话,打印出来的东西肯定是错乱的。

2.2K20

C++11新特性学习笔记

但是,如果程序员为类显式的自定义了非默认构造函数,编译器将不再会为隐式地生成默认无参构造函数。...::move 既然编译器只对右值引用才能调用转移构造函数和转移赋值函数,而所有命名对象都只能是左值引用,如果已知一个命名对象不再被使用而想对调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用...可以对动态资源进行管理,保证任何情况下,已构造的对象最终会销毁,即的析构函数最终会被调用。...int main() { //使用std::functionstd::bind存储和操作lambda表达式 function f1 = [](int a) { return...这个过程有点类似于,公司部门里,使用着打印机打印东西的同时(还没有打印完),别人刚好也在此刻使用打印机打印东西,如果不做任何处理的话,打印出来的东西肯定是错乱的。

2K20

std::functionstd::bind使用总结

C++中函数指针的用途非常广泛,例如回调函数,接口类的设计等,但函数指针始终不太灵活,只能指向全局或静态函数,对于类成员函数、lambda表达式或其他可调用对象就无能为力了,因此,C++11推出了std...std::function vs 函数指针 C++函数指针相信大家用的很多了,用法最广泛的应该就是先定义函数指针的类型,然后在声明一个函数指针的变量作为另一个函数的入参,以此作为回调函数,如下列代码所示...std::function可以说是函数指针的超集,除了可以指向全局和静态函数,还可以指向彷函数,lambda表达式,类成员函数,甚至函数签名不一致的函数,可以说几乎所有可以调用的对象都可以当做std:...2秒左右,而std::function要比函数指针慢2秒左右,这么少的损耗如果是对于调用次数并不高的函数,替换成std::function绝对是划得来的。...跟std::bind一样,如果我们在iOS中使用lambda表达式,而且函数体内捕获了外部变量,我们需要注意避免出现循环引用。

10.7K92

C++11常用新特性快速一览

注意值捕获的前提是变量可以拷贝,且被捕获的变量在 lambda 表达式被创建时拷贝,而非调用时才拷贝。如果希望 lambda 表达式在调用时能即时访问外部变量,我们应当使用引用方式捕获。...如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量。...原因:lambda 表达式可以说是就地定义仿函数闭包的“语法糖”。捕获列表捕获住的任何外部变量,最终会变为闭包类型的成员变量。...不过这没有关系,因为通过明确的写出 std::move(a),我们很清楚我们的意图:亲爱的转移构造函数,你可以对 a 做任何想要做的事情初始化 c;不再需要 a 了,对于 a,您请自便。...因此以上对 parameter 的转移是不允许的,需要使用 std::move 显示转换成右值。

2.5K50

C++ Lambda 本质 & 变量捕获

C++ 11 引入 lambda 之后,可以很方便地在 C++ 中使用匿名函数,这篇文章主要聊聊其背后的实现原理以及有反直觉的变量捕获机制。...C++ Lambda 的函数结构 [capture_list](parameter_list) -> return_type {function_body} 其中,capture_list 表示捕获列表...::cout << "area of circle with radius 2.0 : " << area(2.0) << std::endl; } 这里选择了 by-copy (=) 的方法捕获...line 15, 捕获的变量在这里,会被转化为类该类的属性,并在构造的传入捕获的参数 (line 15 & line 24) ps: 其实也可见 C++ 中 lambda 的实现和 Java 的 lambda...实际场景中,应该根据实际的需要(主要考虑生命周期),选择是使用 by-copy 还是 by-reference 捕获 this.

1.2K70

C++11『lambda表达式 ‖ 线程库 ‖ 包装器』

不行,线程还没有完全创建,传入的对象也无法使用,也能通过捕获列表进行引用捕捉,不过同样无法使用 如此一,想要在 线程回调函数 内获取 线程 id 还不是一件容易的事,好在 C++11 中还提供了一个...解决方法有两个: 在 catch 代码块中手动释放锁资源(不推荐) 使用 RAII 风格的锁(推荐) RAII 风格就是 资源获取就是初始化 ,也就是利用对象出了作用域会自动调用析构函数这个特性,...判断待打印的数字是否符合范围,如果不符合就不进行打印,直接 break 结束循环,因为这里是 RAII 风格的锁,所以不必担心死锁问题 2.4.atomic 原子操作类 在学习 atomic 原子操作类...; } 如果包装 非静态成员函数 就有点麻烦了,因为 非静态成员函数 需要借助 对象 或者 对象指针 进行调用 解决方法是:构建 function 包装器时,指定第一个参数为类,并且包装时需要取地址...auto 自动推导 bind 生成的可调用对象类型外,还可以使用 包装器 包装出类型 // 使用包装器包装出类型 function RFunc = bind(Func

25710
领券