读书笔记之:More Exceptional C++ (2002) [++]
1. std::cin和std::cout的类型是什么?
简单的回答,cin实际上是:
std::basic_istream<char,std::char_traits<char>>
cout实际上是:
std::basic_ostream<char,std::char_traits<char>>
首先,cin和cout具有的类型分别是std::istream和std::ostream,接着,这些类型是std::basic_istream<char>和std::basic_ostream<char>的typedef,最后,考虑到模板参数的默认值,得到上面的答案。
#include <iostream>
int main(int argc,char *argv[]){
using namespace std;
(argc>2?ofstream(argv[2],ios::out|ios::binary):cout)
<<(argc>1?ifstream(argv[1],ios::in|ios::binary):cin)
.rdbuf();
}
但是我在gcc上进行实验的时候,不成功。错误如下:
改成下面的方式就可以了
#include <fstream>
int main(int argc,char* argv[]){
using namespace std;
fstream in,out;
if(argc>1) in.open(argv[1],ios::in|ios::binary);
if(argc>2) out.open(argv[2],ios::out|ios::binary);
(out.is_open()?out:cout)
<<
(in.is_open()?in:cin).rdbuf();
}
原因应该是输入输出流禁止复制
3. STL中的remove完成了什么功能?
写一段代码删除vector中值为val的代码:
两种方法,一种是遍历,同时使用erase操作,另一种是使用STL中的remove算法。
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
void remove_v(vector<int>& v,int val){
vector<int>::iterator ite;
for(ite=v.begin();ite!=v.end();){
if(*ite==val)
ite=v.erase(ite);
else
++ite;
}
}
void remove_v2(vector<int>& v,int val){
v.erase(remove(v.begin(),v.end(),val),v.end());
}
int main(){
int a[]={1,2,3,1,2,3,1,2,3,3,3,0,3,8};
int len=sizeof(a)/sizeof(a[0]);
vector<int> v(a,a+len);
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
cout<<endl;
int val=3;
remove_v2(v,val);
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
cout<<endl;
}
删除容器中的第n个元素,有两种方法,作为比较:
第一种是顺序遍历到第n个元素,然后将之后的元素往前移一位
T remove_nth(T first, T last ,size_t n){
assert(last-first>=n);
for(;n>0;++first,--n);
if(first!=last){
T dest=first;
return copy(++first,last,dest);
}
return last;
}
第2种方法是利用函数对象,当它被调用n次之后返回true,将该函数对象应用于remove_if 函数
public:
FlagNth(size_t n):current_(0),n_(n){}
template <typename T>
bool operator()(const T&){
return ++current_==n_;
}
private:
size_t current_;
const size_t n_;
};
//....
remove_if(v.begin(),v.end(),FlagNth(3));
4. C++中的谓词predicate
谓词是一个函数指针或函数对象(一个提供了函数调用运算符operator()的对象),针对一个"关于对象的提问",它做出"是"或"否"的回答,STL中的许多算法使用predicate,用以对它们所操作的每个元素进行某种判断。
对一般的predicate来说,拷贝和原始对象是等同的。二者可以互换使用。
但是对于状态性predicate,这个却是不可预测的。
状态性predicate和非状态性predicate的主要区别在于:对于状态性predicate来说, 拷贝和他们本身不是等同的。
5. 可扩充的模板:使用继承还是traits
什么是traits类
6. vector<bool>
7. vector和deque
调用reserve()永远不会缩小vector的容量,调用reserve()只能增加容量,或者,如果容量已经足够,他就什么事都不做。
将vector缩小到合适大小的正确方法
8. set和map
map中的键值对是不能修改的,下面的方式可能修改成功,但是会破坏map的结构:
如果要修改键值的话,可以采用先删除再插入的方式。
9. 等同的代码吗?
(1) 下面的代码做了些什么?
//例9-1
f(a++);
请回答得尽可能的完整,涵盖所有的可能性。
(2)下面两段代码有区别吗?
//例9-2(a)
f(a++);
//例9-2(b)
f(a);
a++;
10. 模板特化与函数重载
非模板函数总是优于模板函数,但是非模板函数只有在完全匹配的时候才会被优先选用
11. 内联函数inline
内联函数一定会提高效率吗?
12. 零长度数组是合法的
13. 写一个可以返回自己函数指针的函数
14. 直接初始化与复制初始化