1.标准输入输出流
cin与cout的使用,就不多说了,说一个有关保留小数位数的操作,使用ostream对象的precision()方法,表达的意思是数字总共有几位,注意,此时是包括整数部分的;set()方法表示换成保留小数点后位数。例如
#include<bits/stdc++.h>
using namespace std;
int main()
{
// 请在此输入您的代码
cout.precision(2);
cout.setf(ios::fixed);
cout<<3.1415926<<endl;
cout.unsetf(ios::fixed);
cout<<3.1415926<<endl;
return 0;
}
先是整体位数,在变成小数点位数,再变回来,注意代码实现。
#include<bits/stdc++.h>
using namespace std;
int main()
{
// 请在此输入您的代码
cout<<setprecision(4)<<fixed;
cout<<3.1415926<<endl;
cout<<defaultfloat;
cout<<3.1415926<<endl;
cout<<setprecision(6);
cout<<3.1415926<<endl;
return 0;
}
这是另一种写法,不过需要头文件,代码中我是使用了万能头文件;
下面是有关数据读入的方法:
string s;
getline(cin,s);
cout<<s<<endl;
cout<<s.length()<<endl;
字符串流
类型转换,将"123456"转换成123456
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s("123456");
stringstream ss;
ss<<s;
int i;
ss>>i;
cout<<i<<endl;
return 0;
}
2.容器
2.1 栈
2.2 队列
2.3 链表
2.4双端队列
2.5 vector向量,数组
2.6 map
表,存放一个键key到值value的映射
2.7优先队列
3 函数(算法)
3.1 排序
sort()是优化后的快排
3.2二分
3.3 二分答案
3.4 填充
全排列
4 迭代器 iterator
有趣的操作,就是对容易进行遍历,不过是利用指针操作的;使用begin返回容器第一个元素的位置,然后不断++;直到end;end是最后一个元素的下一个位置;
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int> intVect;
for(int i=0;i<10;i++){
intVect.push_back(i);
}
cout<<"vec: "<<endl;
// for(int i=0;i<10;i++){
// cout<<&intVect[i]<<" ";
// }
// cout<<endl;
// cout<<&intVect.end()<<endl;
vector<int>:: iterator it = intVect.begin(); //定义一个迭代器
/*
begin,end是迭代器的专属函数;
begin表示获取指向第一个元素位置的迭代器。
end表示指向最后一个元素之后的下一个位置的迭代器!!!注意,不是最后一个元素;
因此我尝试相反迭代,也就是从end往start;第一个打印的元素都是0,就是数组范围外的元素,默认为0;而返回不到第一个元素,因为到第一个元素就停止了。
因此正向的迭代终止位置是,最后一个位置的下一个内存,而不是最后一个内存
*/
while(it!=intVect.end()){ //直到遍历到vector最后一位之后
cout<<*it<<endl; //打印迭代器内容
it++; //迭代器不断向后更新
}
// for(std::iterator it2 = intVect.begin(); it2!=intVect.end();it2++){
// }
return 0;
}
简单的迭代器就是这样,实际就是指针的操作,因此可以利用迭代器进行容器赋值,容器读取。可以向前遍历,向后遍历,同样可以随机访问:*(it+2)。跟指针一样。
5右值引用与移动语义
左值表征一个对象,一定占据内存
即使编译器做优化使其实际不占内存
lvalue-》可以被取地址;除非使用const修饰的-》有名字的表达式都是左值,除了枚举
因此将左值放在等式右边,将会报错
rvalue并不表征一个对象,非左值的表达式是右值。-》右值要在等号右边,给左值做处理;
纯右值-》如果一个函数返回一个结构体,需要访问该返回值的某个内部成员变量。此时,该结构体是右值,但,该返回结构体必须占内存,却又满足左值特征,临时占一片地址。上面说的传统右值是临时的,并不会占内存,因此纯右值是一种特殊的右值
根据这种特性,将右值又分为了纯右值prvalue和将亡值xvalue;
右值引用只能被右值表达式初始化。
复制就是复制一份新的数据,但是移动就是将原对象指向资源的指针,赋给新的对象成员,也就是将所有权进行转移,也就是数据的指针指向新对象。
6 智能指针
C++指针得设计存在一系列的使用不方便,比如,对于一个指针,要在合适得地方进行delete;指针的指向变换,容易造成对于同一片区域得多次delete;当指针作为函数参数时,很难确定他是作为数组得首地址,还是单变量得指针,那释放地址得操作更不能确定了,因此C++提供一种智能指针,自动释放内存,且只有一个指针指向该内存,也就是唯一性
#include<iostream>
#include<memory>
class Cat{
public:
Cat(){ this->name = "default"; std::cout<<" con! "<<std::endl;};
Cat(std::string name){this->name=name; std::cout<<" con! "<<std::endl;};
void show(){ std::cout<<this->name<<std::endl;};
void set_name(std::string name){this->name = name;};
~Cat(){std::cout<<" decon!"<<std::endl;};
private:
std::string name;
};
int main(){
Cat* demo1 = new Cat("oo");
//std::unique_ptr<Cat> un_demo1{demo1}; //第一种智能指针创建方式,根据以后裸指针创建
//std::unique_ptr<Cat> un_demo1{new Cat("lk")}; //第二种智能指针创建方式,new一个对象赋值给智能指针
std::unique_ptr<Cat> un_demo1 = std::make_unique<Cat>(); //第三种智能指针创建方式,利用mask_unique
demo1 = NULL;
un_demo1->show();
un_demo1->set_name("new");
un_demo1->show();
//delete demo1;
return 0;
}
首先确定,unique_ptr只能指向一个地址,因此,只能移动所有权,不能复制,将一个指针赋值给另一个智能指针,需要使用move,将地址的所有权转移,move本身是上一节移动语义说到的操作,将左值变成右值.