门户网站做seo,做游戏数据分析的网站,目前做网站的好处,西安网站制作公司哪可变参数模板
可变参数模板对参数进行了高度泛化#xff0c;可以表示任意数目、任意类型的参数#xff1a; 语法为#xff1a;在class或者typename后面带上省略号。
Templateclass ... T
void func(T ... args)
{//
}T:模板参数包#xff0c;args叫做函数参数包 …可变参数模板
可变参数模板对参数进行了高度泛化可以表示任意数目、任意类型的参数 语法为在class或者typename后面带上省略号。
Templateclass ... T
void func(T ... args)
{//
}T:模板参数包args叫做函数参数包 省略号作用 1、声明一个包含0到任意个模板参数的参数包 2、在模板定义的右边可以将参数包展开一个个独立的参数 c11可以使用递归函数的方式展开参数包获得可变参数的每个值。不过这个需要提供一个参数包展开函数和一个递归终止函数。 参数Args…在展开的过程中会递归调用自己每调用一次参数包中的参数就会少一个直到所有参数都展开为止。
右值引用
1、临时对象的深拷贝
一个带有堆内存的类必须提供一个深拷贝的拷贝函数。因为默认的拷贝构造函数是浅拷贝会发生指针悬挂问题两个对象的两个指针指向同一块内存当函数作用结束后两个对象分别调用析构函数错误地将一块内存区析构两次。 提供深拷贝地构造函数可以保证正确但是会造成额外地性能损耗。 GetA函数会返回临时变量然后通过这个临时变量拷贝构造一个新的对象a临时变量在拷贝构造完成之后就销毁了。如果这个堆内存很大地话拷贝构造的代价很大。也就是说每次产生临时变量都会造成额外地性能损失。
2、移动构造函数解决问题
A(A a) :m_ptr(a.m_ptr){a.m_ptr nullptr;cout move construct endl;}move construct这个构造函数是移动构造函数它的参数是一个右值引用类型A。 它仅仅是将指针的所有者转移到了另一个对象上同时将参数对象a的指针置空。也就是说这里仅仅做了浅拷贝从而避免了临时变量的深拷贝问题。
为什么能够匹配到这个构造函数呢 这个构造函数只能够接受右值参数而函数的返回值就是右值所以就会匹配到这个构造函数。A看作临时值的标识。
对于临时值我们仅仅需要做浅拷贝即可无需再做深拷贝从而解决了临时变量拷贝构造产生的性能损失问题。这就是移动语义
3、左值借助移动语义优化性能
我们可以使用std::move将左值转换为右值引用。 move是将对象资源的所有权从一个对象转移到另一个对象只是转移没有内存的拷贝这就是所谓的move语义。 通常这样使用 使用move将左值转换成右值引用。应用移动语义调用移动构造函数。 我们需要记住 如果一个对象内部有较大的内存或者动态数组就很有必要写move语义的拷贝构造函数和赋值函数避免无所谓的深拷贝以提高性能 左值引用和右值引用本质作用都是减少拷贝提高效率。 右值引用可以弥补左值引用不足的地方右值引用做参数和做返回值减少拷贝的本质是利用了移动构造和移动赋值。 左值引用 做参数 void func(T x) - void func(T x) 减少了传参过程中的拷贝 做返回值 T func() - T func() 减少返回过程中的宝贝返回对象除了作用域不存在了就不能使用传引用了 右值引用 做参数 void func(T x) : 使func内部不再将x拷贝构造到容器空间上而是采用移动构造 做返回值利用移动构造减少拷贝。 4、完美转发
右值引用会在第二次之后的参数传递过程中右值属性丢失在下一层调用中会识别成左值。 C11引入完美转发的概念完美转发是指在函数模板中完全依照模板的参数的类型将参数传递给函数模板中调用的另外一个函数
#includeiostream
using namespace std;
void Fun(int x)
{cout 左值引用 endl;
}
void Fun(int x)
{cout 右值引用 endl;
}templatetypename T
void PerfectForward(T t)
{Fun(std::forwardT(t));
}int main()
{//右值引用PerfectForward(10);int a;//左值引用PerfectForward(a);//右值引用PerfectForward(std::move(a));return 0;
}lambda表达式
lambda表达式定义了一个匿名函数并且可以捕获一定范围内的变量定义如下 [capture] (params)mutable-return_type{statement}
[capture] :捕获列表捕获上下文变量以供lambda使用。编译器根据[]符号来判断接下来的代码是否是lambda函数。 (params):参数列表与普通函数的参数列表一致如果不需要传递参数可以连同括号一起省略 mutable修饰符默认情况下lambda函数总是一个const函数mutable可以取消其常量性。使用该修饰符时参数列表不可省略 return_type:返回值类型 {statement}函数体内容与普通函数一样除了可以使用参数之外还可以使用所捕获的变量。
lambda表达式与普通函数最大的不同就是它可以通过捕获列表访问一些上下文的数据。
[var] : 表示以 值传递方式 捕获 变量var [] : 表示以 值传递方式 捕获 所有父作用域的变量(包括this) [var] : 表示以 引用传递方式 捕获 变量var [] : 表示以 引用传递方式 捕获 所有父作用域的变量(包括this) [this] : 表示以 值传递方式 捕获当前的this指针
lambda的类型被定义为“闭包”的类通常用于stl库中。在某些场景下用于简化仿函数的使用同时lambda作为局部函数也会提高复杂代码的开发速度。可以在函数内部重用代码不需要费心设计接口。 下面是示例代码
#includeiostream
using namespace std;int main()
{int a 0, b 1;//实现ab的lambda表达式auto add1 [](int x, int y)-int {return x y;};cout add1(a, b) endl;auto add2 [a, b]()-int {return a b;};cout add2() endl;cout a b endl;//实现a和b的交换auto swap1 [](int x, int y){int tmp x;x y;y tmp;};swap1(a, b);cout swap1() a b endl;auto swap2 [a, b]()mutable{int tmp a;a b;b tmp;};swap2();cout swap2() a b endl;return 0;
}