当前位置: 首页 > 网络应用技术

C ++ 11通常使用的新功能快速列表

时间:2023-03-07 14:40:27 网络应用技术

  NULLPTR的目的是替换NULL。

  从某种意义上说,传统的C ++将把零作为同一件事。这取决于编译器如何定义空。一些编译器将null定义为(void),而有些则将其直接直接带入。将其定义为0。

  C ++不允许直接将隐藏的void直接转换为其他类型,但是如果将null定义为(void)0),则当编译C ++ HAR CH = NULL时;零必须定义为0。

  这仍然会导致问题,这将导致C ++的重负荷特性中的混乱。考虑:

  对于这两个函数,如果将空定义为0(null);该声明将称为Foo(INT),这将导致代码违反直觉。

  为了解决此问题,C ++ 11引入了NULLPTR关键字,专门用于区分空气指针,0。

  NULLPTR的类型是NullPtr_T,可以将其隐式转换为任何指针或成员指针的类型。也可以与他们进行比较。

  当您需要使用NULL时,请养成直接使用NullPTR的习惯。

  C ++ 11介绍了两个关键字,即自动和声明类型,以实现类型推导,并让编译器担心变量的类型。

  汽车

  Auto很久以前就进入了C ++,但他总是作为存储类型指示器,并与寄存器共存。变量。寄存器被放弃,自动的语义变化非常自然。

  使用自动派生的最常见和重要的示例之一是迭代器。过去,我们需要编写这样的迭代器:

  并在自动之后:

  其他一些常见用法:

  注意:自动不能用于功能参数,因此无法编译以下练习(考虑到重载的问题,我们应该使用模板):

  此外,自动不能用于得出数组类型:

  声明

  声明类型的关键字似乎可以解决变量类型派生的缺陷,以求解变量类型导数的缺陷。ITS用法与SizeOf相似:

  在此过程中,编译器分析表达式并获得其类型,但实际上并未计算表达式的值。

  有时,我们可能需要计算表达式的类型,例如:

  尾巴返回类型,自动和声明类型可能认为您可能会认为自动可以用来得出函数的返回类型。请考虑一个示例的其他方法的示例,我们必须在传统的C ++中写下此示例:

  这种代码实际上很丑陋,因为当程序员使用此模板函数时,他们必须清楚地指出返回类型。但实际上,我们不知道add()函数会做什么以及获得了哪种返回类型。

  该问题在C ++ 11中解决。尽管您可以立即反映使用celltype中x+y的类型,但请编写此代码:

  但是实际上,不能编译此类写作。这是因为X和Y在编译器读取frevletype时尚未定义(X+Y)。在解决此问题的过程中,C ++ 11还引入了拖延返回类型,使用自动关键字返回返回类型的类型:

  从C ++ 14中,它可以直接允许正常函数具有返回值推导,因此以下写作方法变得合法:

  基于范围的Forvoy C ++ 11引入了基于范围的迭代写作。我们有一个像python一样简单的周期语句。最常用的std :: vector遍历将介绍原始内容:

  它变得非常简单:

  C ++ 11提供了统一的语法来初始化任何对象,例如:

  C ++ 11还将初始化列表的概念绑定到类型,并将其称为std :: prinitizer_list,允许构造函数或其他函数使用参数之类的初始列表。这是类对象和普通阵列的初始化POD的初始化方法提供了一个统一的桥梁,例如:

  外部模板

  在传统的C ++中,使用时,该模板将被编译器制度化。实例。我们无法通知编译器不要触发模板实例。

  C ++ 11介绍了外部模板,在特定位置实例中扩展了原始强制编译器的语法,因此可以在模板实例化模板时明确告知编译器:

  技能“ >>”

  在传统的C ++编译器中,>>将被视为处理处理的正确运动公式,但实际上,我们可以轻松地编写嵌套模板的代码:

  这不能在传统的C ++编译器下进行编译,并且C ++ 11的开始,连续的右键支架将成为合法的,并且可以成功编译。

  类型的AILARY模板

  在传统的C ++中,Typedef可以为该类型定义一个新名称,但是无法为模板定义新名称。由于模板不是类型。例如:示例:

  C ++ 11使用用于引入以下写作形式,并且还支持对传统Typedef的相同效果:

  我们可以为默认模板参数定义一个添加功能:

  但是,在使用中,发现如果您使用add,则必须每次指定模板参数的类型。在C ++ 11中提供了便利性,可以指定模板的默认参数:

  结构

  C ++ 11介绍了调试结构的概念,该概念允许构造函数调用同一类中一个构造函数中的另一个构造函数,以实现简化代码的目的:

  遗产

  在继承系统中,如果派生类要使用基类的构造函数,则需要在构造函数中明确声明。如果基类具有大量不同版本的构造函数,以便许多相应的相应“透明度”构造函数可以写在衍生类别中。如下:

  C ++ 11的继承结构:

  如果相关代码未使用继承构造函数,则编译器将不会为其产生真实的功能代码,因此,与传输基类的各个构造函数相比,目标代码空间更加保存。

  Lambda表达式实际上提供了类似于匿名函数的功能,并且匿名函数需要一个函数,但是它们不想努力工作以命名函数。

  Lambda表达的基本语法如下:

  捕获列表:lambda表达式捕获列表可很好地控制lambda表达式可以访问的外部变量以及如何访问这些变量。

  int a = 0,b = 1;auto f1 = [] {return a;};//错误,没有外部变量auto f2 = [&] {返回a ++};// ok auto f3 = [=] {returna;};// ok auto f4 = [=] {返回a ++;};//错误,a通过复制捕获,并且自动f5 = [a] {返回a+b;};// errorthere是无捕获变量b auto f6 = [a,&b] {返回a+(b ++);};// ok auto f7 = [=,&b] {返回a+(b ++);// 好的

  Lambda表达的一般原则:

  lambda表达式无法分配:

  闭合类型禁用了分配运算符,但是复制构造函数并未禁用,因此您仍然可以使用lambda表达式来初始化另一个lambda表达式来生成复制。

  在各种捕获方法中,最好不要使用[=]和[&]默认来捕获所有变量。

  捕获所有变量的默认引用,您可能会有一个悬架参考,因为参考捕获不会扩展不会扩展的变量的生命周期:

  std ::功能 add_x(int x){return [&](int a){return x + a;};} 1 2 3 4上面函数返回lambda表达式。参数x只是一个临时变量。它被破坏了,但是返回的lambda表达式引用了该变量。当调用表达式时,引用了垃圾值,这将产生毫无意义的结果。在上述情况下,使用默认值方法可以避免悬架参考问题。

  但是,仍然存在使用默认值捕获所有变量的风险。查看以下示例:

  类过滤器{public:filter(int divisorval):divisor {divisorval} {}

  私人:int divisor;};

  该类中有一个成员方法可以返回lambda表达式。此表达式使用类数据成员divisor。并使用默认值捕获所有变量。您可以使用以下代码验证:

  //类的方法,无法编译以下内容,因为除数不在lambda捕获范围内

  在原始代码中,Lambda表达式实际捕获了该指针的副本,因此原始代码等同于:

  尽管它仍然是由职责捕获的,但捕获实际上等同于以参考方式捕获当前的类对象,因此lambda表达式的闭合绑定到类对象。这是非常危险的,因为您仍然可以使用此lambda表达式之后,在对象类似于变性之后,那么“悬架参考”的问题也将发生。因此,使用默认值来捕获所有变量仍然是不安全的,主要是由于指针变量的复制。实际上,它仍然通过引用传递。

  lambda表达式可以为相应的函数指针分配值。但是使用函数指针并不是那么方便。< functional >标题文件提供了一个多态函数对象封装std ::函数,该功能类似于函数指针。它可以绑定任何类型的函数对象,只要参数与返回类型相同。两个int功能包装器:

  lambda表达式的更重要的应用是可用于函数的参数,通过这种方式可以实现回调函数。

  最常用的是在STL算法中,例如,您要计算符合数组中特定条件的元素的数量,并通过lambda表达式提供条件以传递到Count_if函数:

  对于另一个示例,您要生成斐波那ac cis号,然后将其保存在数组中。目前,您可以使用生成功能并协助Lambda表达式:

  当您需要穿越容器并操作每个元素时:

  大多数STL算法在Lambda表达中可能非常灵活,以达到所需的效果。

  std ::数组保存在堆栈内存中。与堆内存中的STD ::向量相比,我们可以灵活地访问其中的元素以获得更高的性能。

  std ::数组在编译时将创建一个固定的 - 尺寸数组。STD ::数组不能转换为指针。使用std ::数组仅指定其类型和大小:

  当我们开始使用STD ::数组时,我们将不可避免地遇到与C型式兼容的接口。这里有三种方法:

  std :: forward_list是一个列表容器,它基本类似于std :: list。从实现两个链接的std :: list的实现,std :: forffert_list使用一个-way -way链接列表进行实现,提供o(1)元素插入,并且不支持快速随机访问(这也是链接列表的特征)。库容器中唯一不提供size()方法的容器。- 道路迭代,比STD ::列表的空间利用率更高。

  C ++ 11介绍了两组无序容器:STD :: Unordered_map/std :: unordered_multimap和std :: Unordered_set/std :: Unordered_multiset。

  无序容器中的元素未分类,插入和搜索元素的平均复杂性是通过哈希形式的O(常数)。

  使用元组有三个核心功能:

  std :: make_tuple:结构元组std :: get:获取元组std的某个位置的价值:: tie:

  两个金属组的合并可以通过std :: tuple_cat实施。

  正则表达式描述了字符串匹配的模式。通常使用正则表达式实现以下三个需求:

  C ++ 11提供的正则表达式库操作std :: String对象,并初始化模式std :: Regex(本质上是STD :: BASE_REGEX),并匹配std :: Regex_match以生成std :: Smattstd :: match_results)。

  我们通过一个简单的示例简要介绍了此库的使用。请考虑以下正则表达式:

  [A-Z]+。TXT:在此正则表达式中,[A-Z]表示一个小猫字母,+可以使上一个表达式匹配多次,因此[A-Z]+可以匹配由正则表达式中上方或上方的小写字母组成的字符串。它代表任何角色的匹配,在公义之后,它表示匹配的角色。最后一个txt表示三个字母与txt严格匹配。因此,此正则表达式的内容是名为素描字母的文本文件。STD:: REGEX_MATCH用于匹配字符串和正则表达式,并且有许多不同的负载表单。最简单的表单是匹配std :: string和std :: Regex匹配的表单。当匹配成功时,它将返回true,否则将返回错误。例如:

  另一个常用的表单是STD :: String/smatch/std :: Regex.Smatch的三个参数的三个参数,将其定义为std :: match_results,它是sub -string iterator type.use std ::::::::: results.use std ::::::Smatch轻松获得匹配的结果,例如:

  以上两个代码段的输出结果是:

  std :: thread std :: mutex/std :: simolor_lock std :: future/std :: packaged_task std :: procention_variable

  代码汇编需要使用-pthread选项

  首先看一个直觉感受的简单示例:

  如果使用以下复制构造函数:

  在上面的三行中,只有第一行(第1行)的x -depth副本,因为我们可以在背面使用x,x是左值。

  第二行和第三行的参数是正确的值,因为表达式生成的字符串对象是匿名对象,并且以后无法使用它。

  C ++ 11引入了一种称为“正确的值参考”的新机制,以便我们可以通过重载直接使用正确的值参数。我们要做的是编写一个具有正确值参考的构造函数作为参数:

  我们没有将数据复制在桩内存中,而仅复制指针并将源对象的指针放空。实际上,我们“窃取”属于源对象的内存数据。由于源对象是正确的值并且将不再使用,客户不会注意到源对象已更改。在这里,我们没有真正复制它,因此我们将该构造函数称为“移动构造函数”。他的工作是将资源从一个对象转移到另一个对象,而不是复制它们。

  使用正确的值参考,让我们看一下分配运营商:

  请注意,我们直接通过参数传递,以便像其他任何对象一样初始化。因此,确切地说是如何初始化?对于C ++ 98,答案是复制构造函数,但是对于C ++ 11,编译器将根据参数或正确的值选择构造函数和传输构造函数。

  如果是a = b,则将调用复制构造函数来初始化该构造(因为b是左值),并且分配运算符将与新创建的对象和-Depth copy交换数据。这是复制的定义和交换的用法方法:构造一个副本,用副本交换数据,并让副本在动作范围中自动销毁。在这里相同。

  如果是a = x + y,则将调用传输构造函数以初始化(因为x + y是正确的值),因此这里没有深层副本,只有有效的数据传输。仍然是一个独立的对象,但是他的结构函数是没有用的,因此不需要复制堆中的数据,而只是转移。不需要复制他,因为x+y是正确的价值,而且它再次从正确值的对象转移是没有问题的。

  摘要:将构造函数复制以执行深层复制,因为不得更改源对象本身。但是,传输构造函数可以复制指针并放置源对象的指针。在此形式中,这是安全的,因为用户无法再使用此对象。

  下面我们进一步讨论正确的价值参考并移动语义。

  C ++ 98标准库提供了唯一的智能指针STD :: auto_ptr,该库已在C ++ 11中被放弃,因为其“复制”行为是危险的。

  注意B如何使用A初始化。它不会复制三角

  auto_ptr的复制构造函数看起来像这样(简化):

  AUTO_PTR的危险是应该复制它,但实际上是转移。调用已转移的Auto_ptr的成员功能将导致不可预测的后果。因此,如果他被转移,则必须非常谨慎地使用AUTO_PTR。

  显然,必须在auto_ptr对象的auto_ptr值类型的auto_ptr值类型之间存在一些潜在差异,并保留呼叫-Type make_triangle()。每个呼叫都会创建一个新的auto_ptr对象。在此实际上是lvalue的一个示例,而make_triangle()是正确值的示例。

  像a一样移动左值是非常危险的,因为我们可以称呼a的成员函数,这将导致不可预测的行为。另一方面,传输正确值(如make_triangle()的正确值非常安全,因为复制了之后构造函数,我们不能使用此临时对象,因为转移后的临时对象将在下一行之前被销毁。

  我们现在知道传输左值非常危险,但是转移的正确值非常安全。如果C ++可以将左和右值与语言级别的支持区分开,我可以完全持续到绝对左值转移或呼叫时暴露左值的传输,以免我们无意中转移左值。

  C ++ 11的答案是正确的值参考。正确的值参考是正确值的新类型的参考,语法为X &&。现在称为旧报价X&现在称为左值value参考。

  使用正确值引用X &&作为最有用的功能的最有用的功能之一是传输constructor x :: x(x && source)。它的主要功能是将源对象的本地资源传输到当前对象。

  在C ++ 11中,它已被替换,后者是正确的值参考。

  其传输结构功能:

  此传输构造函数与构造函数在auto_ptr中的构造函数相同,但是它只能接受正确的值作为参数。

  第二行无法编译,因为A是左值,但是参数unique_ptr &&源只能接受正确的值。这正是我们所需要的,消除了危险的隐藏转移。第三行编译没有问题,因为make_triangle()是正确的值。传输构造函数将将临时对象的所有权转移到对象C。这正是我们所需要的。

  有时,我们可能需要传输左值,也就是说,有时我们希望编译器将左值视为右值,以便我们可以使用传输构造函数,即使这有点不安全。对于此目的,C标准库中的++ 11的标头文件< utility >它提供了一个模板函数std :: move。

  以下是如何正确传输左值的方法:

  请注意,在第三行之后,不再具有三角形对象。但这无关紧要,因为通过清楚地写下std :: move(a),我们知道我们的意图:亲爱的转移结构功能,您可以做任何事情想开始初始化c;我不再不再长nevereed a,因为a,请做自己。

  当然,如果您在使用Mova(a)后继续使用A,则无疑是石头砸碎脚的石头,或者会导致严重的运行错误。

  简而言之,std :: move(some_lvalue)将左值转换为右值(可以理解为类型转换),从而使后续转移成为可能。

  一个例子:

  上面的参数,其类型是正确的值参考,它只能指示参数是指对正确值的引用,而参数本身是左值(确定为rvalue参考的内容可以是lvalues或rvalues。区别标准是:如果它具有名称,则是一个lvalue。它是一个rvalue。)

  因此,不允许上述参数的传输。它需要使用std ::移动以显示过渡到正确的值。参考材料:C ++ 11常用新功能Quick list_jiange_zh博客