sort()的第三个参数
1.sort函数包含在头文件为#include<algorithm>
的c++标准库中,调用标准库里的排序方法可以实现对数据的排序,但是sort函数是如何实现的,我们不用考虑!
2.sort函数的模板有三个参数:
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
1)第一个参数first:是要排序的数组的起始地址。
2)第二个参数last:是结束的地址(最后一个数据的后一个数据的地址)
3)第三个参数comp是排序的方法:可以是从升序也可是降序。如果第三个参数不写,则默认的排序方法是从小到大排序。
int arr[10] = {4,3,2,5,1,7,6,8,9,12};
int len = sizeof(arr)/sizeof(int);
sort(arr,arr+len);
至此,我们可以得到一个升序的数组
{1,2,3,4,5,6,7,8,9,12}
而如果我们需要一个降序的数组,就得自己定义“规则”函数
bool cmp(int x,int y){
return x>y;
}
sort(arr,arr+len,cmp);
第三个参数也叫谓词,对于
sort()
函数的谓词,C++
官方也给出了升序和降序的
#include<functional>
greater<int>()
less<int>()
sort()简单介绍完,该今天的角儿上场了
lambda表达式
lambda表达式,又称为匿名函数,顾名思义lambda表达式就是一个函数,只是不需要为它定义函数名;对于一些实现小功能的函数,可以不需要特别去定义再声明,如上面提到的sort()第三个参数,而使用lambda表达式会更加方便。
简单的介绍一下啊,lambda表达式大概分为三部分
[] () {};
[]
是捕获列表
[=]
表示捕获从lambda表达式所在的作用域的所有局部变量,是值传递方式
[&]
表示捕获从lambda表达式所在的作用域的所有局部变量,是引用传递方式
- 上面所说的所有局部变量,包括lambda所在类的this
[a]
表示只捕获并值转递a
[&a]
表示只捕获引用传递a
[=,&a,&b]
表示除了a
,b
引用传递,其余变量值传递
[&,a,b]
表示除了a
,b
值传递,其余变量引用传递
()
是参数列表
小括号()
里的参数,用于函数体{}
,和平常的函数参数列表无异
参数可以值传递,也可以引用传递
{}
是函数体
lambda表达式功能的具体实现,没啥可说的
倘若lambda表达式要return
,则需要在函数体{}
前加上->type
即[](int a,int b)->bool{ return a>b;}
虽然好像这里bool
可以省去,但代码规范点总是没错的
函数体{}
不允许修改捕获列表[]
的值传递参数
mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词
#include<bits/stdc++.h>
using namespace std;
int main() {
int a = 10;
int b = 100;
[=](){a=a+10;cout<<a<<endl;}();
return 0;
}
若要修改,则需要关键字mutable
#include<bits/stdc++.h>
using namespace std;
int main() {
int a = 10;
int b = 100;
[=]()mutable{a=a+10;cout<<a;}(); // 20
cout<<a; //10
[&](){b+=b;cout<<b;}(); //200
cout<<b; //200
return 0;
}
函数体{}
后再加个小括号()
,就可以自己调用自己;
用lambda
表达式实现sort()
降序
#include<bits/stdc++.h>
using namespace std;
int main() {
int arr[] = {4,2,3,5,1,7,6,9,8,12};
int len = sizeof(arr)/sizeof(int);
sort(arr,arr+len,[](int a,int b){ return a>b;});
//sort(arr,arr+len,[](int a,int b){ return a>b;});
for(int i:arr) cout<<i<<" ";
return 0;
}
执行完成,耗时:0 ms
12 9 8 7 6 5 4 3 2 1
左右值
先区分左值和右值
左值(lvalue):一个标识非临时性对象的表达式。可以将程序中所有带名字的变量看做左值。
右值(rvalue):相对的,右值标识是临时性对象的表达式,这类对象没有指定的变量名,都是临时计算生成的。
vector<string> arr(3);
const int x = 2;
int y;
int z = x + y;
string str = "foo";
vector<string> *ptr = &arr;
这里,x,y,z,str,*ptr都是左值;而2,x+y,“foo”,&arr都是临时性的右值
左值引用
其实左值就是平常所说的变量,而左值引用就是普通的引用,用&
符号进行引用
在定义左值引用时,=
右边的要求是一个可修改
的左值。
#include <stdio.h>
int main()
{
const int x = 5;
int y = 1;
int z = 1;
int & tmp1 = x; // ERROR:x不是一个可修改的左值
int & tmp2 = 5; // ERROR:5是一个右值
int & tmp3 = y + z; // ERROR:y+z是一个右值
return 0;
}
可以看出,一个常量左值,没法被左值引用
int& tmp4 = y;
int& tmp5 = z;
这是合法的左值引用
右值引用
右值引用,使用&&
进行
#include <stdio.h>
int main()
{
int a = 5;
int && x = 5;
int && y = a+5;
return 0;
}
左值引用的一些用途
- 作为复杂名称变量的别名
- 用于for循环
- 避免复制大的变量
- 参与函数的参数传递
对于第三点,上次回溯的笔记开篇就记载了一个传值引用,相比值传递,不管是时间还是空间,都有明显的缩减
std::swap和std::move
前面讨论左值引用的第三点作用时,谈到可以使用引用来减少复制产生的内存开销。
考虑这样一种情况,在进行元素交换时,我们通常使用一个缓存变量temp来临时保存数据;而对temp直接进行=的赋值操作时,实际上temp复制了一次原有对象的内存,但我们需要只是对象之间的移动而不是复制,而C++STL中的std::move函数便可以达成这一操作。
这可能有些抽象,让我们通过例子来看看:
void swap(vector<string> & x, vector<string> & y)
{
vector<string> temp = std::move(x);
x = std::move(y);
y = std::move(temo);
}
上述例子是C++STL中std::swap的源码之一,相信它很好的示范了std::move是如何使用的,而在源码中使用,也足以说明它的高效。
左右值部分来自Bylight
&
操作符的取址
简单记录一下
int main(){
std::string s = "Oh!!";
std::string *p = &s;
std::cout<<s<<endl<<p;
return 0;
}
&
二进制运算符
在二进制运算中,符号&
称为按位与操作符
而数字的二进制表示中
1
只有最低位是1,其余位是0
奇数最低位也一定是1,偶数最低位肯定是0
int main(){
int oddNumber = 11;
int evenNumber = 20;
std::cout<<(oddNumber & 1)<<endl;
std::cout<<(evenNumber & 1)<<endl;
return 0;
}
&
判断一个整型的奇偶,老方便了
记录几个库函数
a,b都是string,如何实现返回double类型的 a/b
STL中有实现这个功能的函数
字符串转换为浮点型
double atof(const char *nptr);
作用:把字符串转换成浮点数,直至遇到第一个空格
int main(){
string str = "12345";
cout << atof(str.c_str())<<endl; // ASCII to float
return 0;
}
c_str()函数,该函数生成一个指向正规C字符串的指针, 内容与本字符串相同
字符串转换为整型
int atoi(const char *nptr);
作用:把字符串转换成整型数。如果第一个非空格字符不存在或者不是数字也不是正负号则返回零,否则开始做类型转换,之后检测到非数字或结束符 \0 时停止转换,返回整型数。
整型转换为字符串
char* itoa(int value,char* string,int radix);
作用:将value所代表的整数转换为字符串。其中,value是要转换的整数值,string是存储转换后值的字符数组,radix代表进制,radix=10就是十进制,radix=2就是二进制。
#include<iostream>
#include<stdlib.h>
using namespace std;
int main(){
char str[100];
itoa(312,str,2);
cout<<str;
return 0;
}
C++中没有浮点型转换为字符串的函数,但可以将一个浮点型数据打印成字符串
int sprintf(string format, mixed [args]...);
返回值:字符串长度(strlen)
详细参考sprintf()函数详解