一些小笔记(1)

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]表示除了ab引用传递,其余变量值传递
[&,a,b]表示除了ab值传递,其余变量引用传递




()是参数列表

小括号()里的参数,用于函数体{},和平常的函数参数列表无异
参数可以值传递,也可以引用传递




{}是函数体

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;});
  
    forint 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;
}

左值引用的一些用途

  1. 作为复杂名称变量的别名
  2. 用于for循环
  3. 避免复制大的变量
  4. 参与函数的参数传递

对于第三点,上次回溯的笔记开篇就记载了一个传值引用,相比值传递,不管是时间还是空间,都有明显的缩减

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()函数详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值