C++学习笔记

C++学习笔记02
1.类的静态对象:与类本身关联,不需要与每个对象关联
static double rate(return interestRate;),且static声明在类里完成就行,写函数时就不用写了
(注:static函数不包括this指针,所以不能定义为const函数)
在使用时可以使用作用域运算符(::)访问静态成员
2.IO类:不能对流对象进行赋值,不能用流对象作为返回值/形参,不能作为左值修改
读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的

ofstream out("file1");//隐含以输出模式打开文件并截断文件(截断是直接清空文件内容,使文件长度为0)
ofstream out2("file1",ofstream::out);//隐含地截断文件
ofstream app("file2",ofstream::app);//保留文件内容,隐含输出模式

3.string流:

sstream strm;//strm是一个未绑定的stringstream对象
strm.str()//返回strm所保存的string的拷贝    strm.str(s)将srting s拷贝到strm中,返回void

string类型代表的是内存,istringstream类型是从内存读取数据,ostringstream类似是将数据写入内存
4.C++有顺序容器和关联容器。
顺序容器(根据位置访问)类型:1.vector(可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除很慢)
2.deque(双端队列,支持快速随机访问,在头尾增删很快)
3.list(双向链表,只支持双向顺序访问,任何位置增删都快)
4.forward_list(单向链表,只支持单向顺序访问,在链表任何位置增删都快)
5.array(固定大小数组,支持快速随机访问,不能增删)
6.string(类似vector,专用保存字符)
容器均定义为模板类,当用于无构造函数的类似时,必须加元素初始化器:如vectorv1(10,init);//不加init是不对的
又如A类(有构造函数,输入形参为string),string AA(“hello”);vectorobjA(100,AA);//隐式调用构造函数建立100个A类型对象
若构造函数有explicit前缀,即不允许隐式调用构造函数,写成vectorobjA(100,A(AA));就行
5.迭代器范围由一对迭代器表示(左闭合区间),每个容器都定义很多类型,为了使用这些类型,必须显式使用,如vector::iterator iter;
begin和end有多个版本,带r的返回反向迭代器(即末尾是begin),以c开头的返回const迭代器(指针常量)
begin有两种,一种是const成员,返回const_iterator类型(this指针指向const),另一种是非常量成员,返回iterator类型(rbegin、end和rend情况类似),a.begin();主要看a是否是const
容器初始化:
1.将一个容器初始化为另一个容器的拷贝—>list authors = {“A”,“B”,“C”};list list2(authors);
2.迭代器范围拷贝—>deque authors2(authors.begin(),it);//it是一个元素,表示到逐个转化类型到it时就停止,不包含it这个元素
3.与顺序容器(array除外)大小相关的构造函数—>vectorivec(12,2);//12个int元素,每个初始化为2
标准库array具有固定大小,array<int,5>ia1;//5是类型的一部分,这里是大小为5,初始化为int型的0
内置数组不容许直接赋值或拷贝,如int init[5] = {0,1,2,3,4}; int init2[5] = init;//错误
array<int, 5>init = {0,1,2,3,4};array<int,5>init2 = init;//正确,类型匹配即合法
6.容器赋值运算:
1.等号替换
2.初始化列表拷贝
3.swap(a,b)交换a,b【比从b拷贝到a快,因为指向容器的迭代器、引用和指针都还有效,array是一定会失效的,string有优化的】
4.assign(不适用关联容器和array) a.assign(begin,end)//将begin到end范围的元素拷贝到a
a.assign(li)//将a中元素替换初始化列表li的元素
a.assign(n,t)//将a中元素替换为n个值为t的元素
7.顺序容器操作:
01.添加元素(向vector、string或deque插入会使指向容器的迭代器、指针和引用失效)
forward_list有自己的insert和emplace,不支持push_back和emplace_back
vector和string不支持push_front和emplace_front
c.push_back(t)、c.emplace_back(args)//返回void
c.push_front(t)、c.emplace_front(args)//返回void
c.insert(p,t)、c.emplace(p,args)//在迭代器p指向的元素之前创建一个值为t或者args创建的元素,返回指向新添加元素的迭代器
c.insert(p,n,t)//在迭代器p前插入n个t
容器的元素是拷贝
使用emplace操作:构造元素而不是拷贝元素,是可以构造函数构造元素来插入,push_back是不能这样的
顺序容器访问元素操作:at和下标只适用于string、vector、deque和array,back不适用于forward_list
c.back()//返回c中尾元素的引用 c.front() c.at(n)//返回下标为n的元素引用
02.顺序容器的删除操作:forward_list有自己的erase,不支持pop_back;vector和string不支持pop_fornt(可理解vector和string前面是一堵墙)
c.pop_back()//删除尾元素,返回void
c.pop_front()//删除首元素
c.erase§//删除迭代器p指向的元素,返回指向被删元素之后的迭代器
c.erase(b,e)//伤处迭代器b和e之间的元素(b是第一个,e是最后的后一个,删除的是b到e的前一个),返回一个指向最后一个被删元 素之后元素的迭代器
c.clear()//全清,返回void
特殊的forward_list操作(因为它只能往后走,没有前驱):
lst.before_begin()//返回指向首前的迭代器(和尾后一样的不存在元素) lst.cbefore_begin()//返回的是const_iterator
lst.insert_after(p,t)//在迭代器p后插入对象t lst.insert_after(p,n,t)//在迭代器p后插入n个对象t
emplace_after(p,args)//使用args在p后创建一个元素,返回一个指向新元素的迭代器
lst.erase_after§//删除p后元素,返回被删元素之后元素的迭代器
03.顺序容器的改变大小操作:
c.resize(n)//扩大/缩小至n
c.resize(n,t)//扩大至n,多的初始化为t
04.容器大小管理操作:shrink_to_fit只适用于vector、deque和string【只是个请求,并不保证退还内存】 capacity和reserve只适用于vector和string【c.capacity()是查容器大小,c.reserve(n)是设置至少大小为n的容器】
8.string特有的操作:

string s(cp,n);//s是cp指向的数组的前n个字符的拷贝
string s(s2,pos2);//s是从字符串s2从下标为pos2开始的字符的拷贝
string s(s2,pos2,len2);//s是从s2从下标pos2开始的len2个

const char *cp = "Hello World";//以空字符结束   char noNull[]  = {'A','B'};//不以空字符结束
string s1(cp);//拷贝cp直到空字符,s1 = "Hello World"
string s2(noNull,2);//从noNull拷贝两个字符 s2 = "AB"
string s3(noNull);//出错,找不到空字符结束
string s4(cp+6,5);//从cp[6]开始拷贝5个 s4 = "World"
string s5(s1,6,5);//从s1[6]开始拷贝5个
string s6(s1,6);//从s1[6]开始直到结尾
string s7(s1,6,20);//从s1[6]开始,只拷贝到结尾
string(s1,16);//出错,s[16]不存在

子字符串操作:s.substr(pos,n)
9.除了接受迭代器的insert和erase版本,还有接受下标版本:

s.insert(s.size(),5,'?');//在s末尾插入5个?
s.erase(s.size()-5,5);//从倒数第6个开始,删除后面5个元素
//C风格
const char *p = "abcde,fg";s.assign(p,7);//s是取p前7个 s.insert(s.size(),p+7);//s == abcde,fg
s.insert(0,s2,0,s2.size());//在s[0]插入s2中从s2[0]到s2.size()个字符

s.append(s1)//在s尾部插入s1
s.replace(11,3,"abc");//从s的位置11开始,删除3个元素并插入abc

10.string搜索操作:

		s.find(args)//查找s中args第一次出现的位置(args是字符或者单词)
		s.rfind(args)//最后一次出现的位置
		s.find_first_of(args)//在s中查找args中任何一个字符第一次出现的位置
		s.find_last_of(args)//
		s.find_first_not_of(args)//在s中查找第一个不在args中的字符
		s.find_last_not_of(args)//

args四种形式:1.c,pos//在位置pos开始找字符c 2.s2,pos//在位置pos开始找字符串s2 3.cp,pos//在位置pos开始找cp指向的以空字符结尾的C风格字符串 4.cp,pos,n//在位置pos开始查找cp指向的数组的前n个字符

11.比较操作:
s.compare(args);
1.s2
2.pos1,n1,s2//在s的第pos1个字符起的n1个字符与s2比较
3.pos1,n1,pos2,n2
4.cp//C风格的字符串
12.适配器: stack、queue、priority_queue
用法:stack intStack(默认deque)/stack<int , vector> intStack(用容器vector)
栈特有的操作:(默认基于deque实现)s.pop()//删除栈顶元素,但不返回该元素 s.push(item)/s.emplace(args) s.top()//返回栈顶元素
队列(默认基于deque)和优先队列(默认vector): q.pop()//返回queue首元素或priority_queue的最高优先级元素 q.front()//返回首元素或尾元素
q.back()//只适用于queue
q.top()//只适用于priority_queue
13.泛型的:可用于不同类型的容器和不同类型的元素,通过迭代器操作(迭代器不依赖于容器所保存的元素类型,只要有一个迭代器可用来访问元素),find返回标识此元素的值

	int sum = accumulate(vec.cbegin() , vec.cend() , 0);//表示vec全部元素累加,初始累加值为0
	string sum = accumulate(vec.cbegin() , vec.cend() , "");//错误,单纯的“”表示C风格的字符串,而const char*没有+运算符【注:两个string可加,一string一const char*可以加,两const char*不可加】
	equal(r.cbegin() , r2.cbegin())//比较r和r2【r2>=r】
	fill(vec.begin(),vec.end(),12)//将所有元素重置为12	fill_n(vec.begin() , 10 , 0);//重置vec开始10个元素为0
	//插入迭代器back_inserter(是一个函数,接受一个容器的引用,返回绑定该容器的插入迭代器):auto it = back_inserter(vec);//it是迭代器 *it = 0;//然后赋值就行

14.拷贝算法:

ret = copy(begin(a1) , end(a1) , a2);//表示将a1开始到结束的内容赋值给a2,返回a2尾后元素的位置
replace(list.begin() , list.end() , 0 , 42//将全部0换成42
replace_copy(list.cbegin() , list.cend() , back_inserter(vec) , 0 ,42);//表示vec拷贝list,然后vec里的0换成42
elimDups(words);//对words先用sort(words.begin() , words.end())按字典排序,然后再用unique(words.begin() , words.end())删除相邻的相同元素(unique会返回指向最后一个不重复元素的后面位置)
stable_sort(words.begin() , words.end() , isShorter);//第三个参数是一个谓词,返回结果是能当作条件的值

15.lambda表达式(没有名字的内联函数,无返回值)
【若不是获取当前函数之外的参数,就是空的】{【函数执行内容】;}(【直接输对应的实参,或者不要本括号】)

int main(){
	int myV = 42;
	[](int x){cout << x <<endl;}(9);//打印x(=9)	
	auto printX = [](int x){cout << x <<endl;};//相当于给一个函数名?
	printX(14);//打印14
	auto f = [myV]{return myV;};//值拷贝
	auto f2 = [myV]mutable{return ++myV;};//值拷贝形式,拷贝的值要变时要加mutable
	auto f3 = [&myV]{return ++myV;};
	}	

16.参数绑定(bind函数):

bool compare(const string& s , string::size_type sz){return s.size()>sz;}
auto check6 = bind( compare , _1 , 6);
string s = "Hello";
bool b = check6(s);//相当于bool b = compare(s , 6);

bind的参数:auto g = bind(func , a , b , _2 , c , _1); 调用时g(X,Y)相当于func(a , b , Y , c , X)

17.插入迭代器有三种类型:back_inserter()产生一个push_back的,front_inserter产生一个push_front的,inserter产生一个insert的(back总是指向最后,front指向第一个,insert则是最新插入的后面)
iostream迭代器:
istream_iteratorint_iter(cin);//创建一个名为int_iter的迭代器,绑定cin
istream_iteratoreof;//创建一个名为eod的迭代器,默认绑定尾后
ostream迭代器: ostream_iteratorout_iter(cout," “);//创建一个名为out_iter的迭代器,每个值后面都输出一个空格(” ")
out_iter = e;//相当于将e值给输出流,*out_iter++也是和这条语句的迭代器作用一样,只要它是用上面的形式生成的,符号就没有影响,会自增换位置,当然加上去这些符号是为了和普通迭代器统一形式,注意istream生成的符号还是和普通一样有效的
反向迭代器
A B C D
若rcom的位置是A,则rcom.base()指向B,crbegin()指向D

18.泛型算法结构:输入迭代器(只读不写,单遍扫描,只递增),输出迭代器(只写不读,单,增),前向迭代器(读写,多,增),双向迭代器(读写,多,增减),随机访问迭代器
算法重载规范:
重复删: unique(beg,end);//用==比
unique(beg,end,comp);//使用comp比较元素
查找: find(beg,end,val);//找val第一次出现位置
find_if(beg,end,pred);//查找第一个令pred为true的元素位置
翻转: reverse(beg,end);//翻转范围内元素
reverse_copy(beg,end,dest)//逆序拷贝到dext
删: remove_if(v.begin(),v.end(),[](int i){return i%2;})

19.特定容器算法:list和forward_list成员函数版本的算法

lst.merge(lst2);//将来自lst2的并入lst,lst和lst2必须有序,用<运算符
lst.merge(lst2,comp);//使用给定的比较操作
lst.remove(val);//删全部val	lst.remove_if(pred);//删令pred为true的全部
lst.sort(comp);
lst.unique(pred)
lst.splice(args)//【粘到前面】或lst.splice_after(args)

20.关联容器:(按关键字来保存和访问的)map的每个元素都是pair类型
map:关联数组:保存关键字-值对 unordered_map:哈希函数组织的map
set:关键字即值 unordered_set:
multimap:关键字可重复出现的map unordered_multimap:
multiset: unordered_multiset
map<string , size_t> word_cout;
set exclude = {“the” , “and” , “or” , “but”};
string word;
while(cin >> word){++word_cout[word];}

用vector初始化set:例如set iset(ivec.cbegin() , ivec cend());//重复的元素会丢掉
如果一个类型定义了“正常行为”的比较运算符,就能作为关键字

21.pair类型:
pair<string , int> val//和map一样,而pair数据成员是public的,val.first ,val.second直接用
pair对象的函数:pair<string , int> process(vector&v)
{
if(!v.empty()){ return{v.back() , v.back().size()}; }
else { return pair<string , int>{}; }//隐式构造返回值
}
22.额外别名:

set<string>::key_type v1;//v1是string
set<string>::value_type v2;//v2是string
map<string , int>::value_type v3;//v3是pair<const string , int>
map<string , int>::key_type v4;//v4是string
map<string , int>::mapped_type v5;//v5是int

23.关联容器迭代器:
auto map_it = word_count.begin();//*map_it是指向pair<const string,size_t>对象的引用
set::iterator set_it = iset.begin()//set迭代器是const的
添加元素:
auto ret = word_count.insert({“word”,1});//返回的ret.first是一个pair类型,ret.first指向"word"元素,ret.second表示是否插入成功(1或0)
删除元素:
auto num = c.erase(k);//删除每个关键字为k的元素,返回删除数量
auto ite = c.erase§;//删除迭代器p指向的元素,返回一个指向p后的迭代器
auto val = c.erase(b,e);//删除范围元素,返回e

map的下标操作:c[k]//返回关键字为k的元素,没有就新建一个并插入
c.at(k)
访问元素; c.find(k)//返回迭代器,没有就返回尾后迭代器
c.count(k)//返回k的数量
c.lower_bound(k)//c有序才能用,返回第一个不小于k的元素的迭代器
c.upper_bound(k)//有序,大于k
c.equal_range(k)//返回一个迭代器pair,表示等于k的元素范围
24.无序容器:
桶接口:c.bucket_count()//正在使用的桶数目 c.max_bucket_count()//最大桶数 c.bucket_size(n)//第n个桶有多少个元素 c.bucket(k)//元素k在哪个桶
桶迭代:local_iterator//访问桶的迭代器类型 const_local_iterator cbegin(n),c.end(n)//桶n的首元素迭代器和尾后迭代器
哈希策略:c.rehash(n)//重组存储,以前迭代器无效 c.reserve(n)//重组存储,不会打散之前的迭代器
不能直接定义关键字类型为自定义类型的无序容器,为了能将自定义类型用作关键字,我们需要函数来代替==运算符和哈希函数

size_t haser(const Sale_data &s){
	return hash<string>()(s.isbn());//利用标准库hash类型对象来计算,后面的s.isbn()是参数
}
bool eqOp(const Sale_data &lhs , const Sale_data &rhs){
	return lhs.isbn()==rhs.isbn();
}
using SD_mulset = unordered_multiset<Sale_data , decltype(haser)* , decltype(eqOp)*>;//参数是桶大小,哈希函数指针,相等性判断运算符指针
SD_mulset bookstore(42 , haser ,eqOp);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜以冀北

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值