Boolan STL与泛型编程 第二周笔记
OOP(object-orientedprogramming)与GP(generic programming)
对于OOP,数据和操作放在一起,存放在类中。
对于GP,将数据和操作分开来。其操作和数据的连接方式如下图:
采用GP,容器和算法可以分开开发。算法通过迭代器确定操作范围,并通过迭代器取用容器中的元素。
为什么list不能使用全局sort进行排序?
因为全局sort中需要容器能够进行随机访问,而list只能进行顺序访问‘
类模版
基本的模版比较简单,有几个关键的地方如下图黄色部分:
函数模板
函数模版与类模版类似,如下图
这里的class与typename意思相同。
对于”<”的操作符重载,编译器会自己去寻找
对与函数模板使用时不需要写出数据类型,因为编译器会根据参数自己来进行推导
泛化与特化
在类模板中,我们泛化了数据类型,其数据类型可以是各种。但是或许我们会有一种想法,对于特定的某一种数据类型,我们想对其进行特殊的对待,这就是所谓的特化。
其语法示例如下:
偏特化/部分特化
其一,指的是模板有两个或两个以上参数,特化其中一个参数,称之为偏特化。
其二,是对于范围的偏特化,示例如下:
List探索
为了实现list的双向功能,每一个元素除了data之外应该还需要两个指针,分别指向前和后
除了vector,所有容器的迭代器都是一个类,用以实现类似智能指针的功能。
因为容器不是连续的,所以其迭代器不能如一个简单的指针一样进行++操作,从而访问下一个元素。
因为迭代器要模拟指针的操作,所以在迭代器的类中肯定要大量的操作符重载,用以模拟指针。
Vector容器内部含有三个指针,start、finish、end ofstorage,其扩充方式为两倍增长。
本周的作业为创建一个list容器,放置6个整形数值[0,1,30,20,10,0]
1. 从后向前打印出容器内的元素
2. 向list容器后面添加两个元素,并对容器内的值求和并打印
3. 打印链表的中间元素
4. 找到不为0的元素,复制到一个vector中并打印vector元素
思考:
1. 创建一个list,放置6个整形数值
这里采用列表初始化,list<int> wk{0,1,30,20,10,0}
2. 从后向前打印容器元素
考虑采用反向容器迭代器,wk.rbegin()/wk.rend(),
for (autoi = wk.crbegin(); i !=wk.crend(); ++i)
{
cout << *i << endl;
}
3. 向list容器后添加两个元素
wk.push_back
int n =0;
cout << "请输入需要添加的元素个数"<< endl;
cin >> n;
int xn;
int number_count=0;
cout << "请输入"<<n<<"个int型数值"<< endl;
while (cin>>xn)
{
++number_count;
if (number_count < n)
{
wk.push_back(xn);
cout << "请输入下一数"<< endl;
}
else if(number_count=n)
{
wk.push_back(xn);
cout << "输入完毕"<< endl;
break;
}
}
4. 容器内求和
采用算法accumulate, int sum=accumulate(wk.begin(),wk.end(),0)
//求和并打印
cout<<"list容器中所有元素之和="
<< accumulate(wk.cbegin(), wk.cend(), 0)<< endl;
5. 打印链表的中间元素
List不支持随机访问,如何打印其中间元素呢?
List在添加了两个元素后,共有8个整形数值,打印中间元素意思是打印第4个和第5个元素?
那么智能顺序方位list,通过容器大小得出中间值的迭代器,再通过范围for打印中间值
在这一步的时候遇到一个很尴尬的问题,如代码所示,本来打算打印第4和第5个值
intn_count=0;
for (auto i = wk.cbegin();i!=wk.cend() ; ++i)
{
++n_count;
cout << n_count << endl;
if(n_count==wk.size()/2&&wk.size()%2==0)
{
cout << "容器元素数量=" << wk.size() << "为偶数,中间元素有两个,分别是第"<< n_count << "个 " << *i <<
"和第"<<++n_count<<"个"<< *++i<<endl;
break;
}
else if(n_count == wk.size() / 2&& wk.size() % 2 != 0)
{
cout << "容器元素数量="<<wk.size()<<"为奇数,中间元素有1个,为 "<< *++i << endl;
break;
}
}
但是打印结果与预期不符合:
并没有按预期的先输出*i,再输出*++i.
经过思考,最终发现问题出在了endl上。Endl的左右是结束当前行并将缓冲区的内容刷到设备中。因为我是在语句的最终才有endl,所有在*i的内容实际刷写之前*i递增为了*++i,所以在最终刷写后,*i和*++i所指的内容其实都是*++i。
解决办法是在递增之前进行一次缓冲区刷写。
cout<< "容器元素数量= " << wk.size() << "为偶数,中间元素有两个,分别是第" << n_count << "个 "<< *i << flush;
cout<<"和第"<<++n_count<<"个"<< *++i<<endl;
6. 找到不为0的元素
方法一:循环判断,push_back到vector
方法二:找到list为0的元素删除,然后通过传递迭代器参数拷贝一个范围给vector
这里采用方法二:
list<int>temp = wk;
auto value_find = find(temp.cbegin(),temp.cend(), 0);
while (value_find!=temp.cend())
{
temp.erase(value_find);
value_find = find(temp.cbegin(),temp.cend(), 0);
}
vector<int> new_wk(temp.cbegin(),temp.cend());
for (auto x : new_wk)
cout<< x << endl;
最终结果如下: