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,最后,考虑到模板参数的默认值,得到上面的答案。

读书笔记之:More Exceptional C++ (2002) [++]_ios

#include <fstream>
 #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();
 }

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_02

但是我在gcc上进行实验的时候,不成功。错误如下:

读书笔记之:More Exceptional C++ (2002) [++]_ios_03

改成下面的方式就可以了

#include <iostream>
#include <fstream>
int main(int argc,char* argv[]){
    using namespace std;                               
    fstream in,out;
    if(argc>1in.open(argv[1],ios::in|ios::binary);
    if(argc>2out.open(argv[2],ios::out|ios::binary);
    (out.is_open()?out:cout)
        <<
        (in.is_open()?in:cin).rdbuf();
}

 

原因应该是输入输出流禁止复制

3. STL中的remove完成了什么功能?

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_04

读书笔记之:More Exceptional C++ (2002) [++]_模板函数_05

写一段代码删除vector中值为val的代码:

两种方法,一种是遍历,同时使用erase操作,另一种是使用STL中的remove算法。

#include <iostream>
#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个元素,然后将之后的元素往前移一位

template <class T>
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 函数

class FlagNth{
    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));

 

读书笔记之:More Exceptional C++ (2002) [++]_#include_06

4. C++中的谓词predicate

谓词是一个函数指针或函数对象(一个提供了函数调用运算符operator()的对象),针对一个"关于对象的提问",它做出"是"或"否"的回答,STL中的许多算法使用predicate,用以对它们所操作的每个元素进行某种判断。

对一般的predicate来说,拷贝和原始对象是等同的。二者可以互换使用。

但是对于状态性predicate,这个却是不可预测的。

状态性predicate和非状态性predicate的主要区别在于:对于状态性predicate来说, 拷贝和他们本身不是等同的。

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_07

 

5. 可扩充的模板:使用继承还是traits

什么是traits类

读书笔记之:More Exceptional C++ (2002) [++]_模板函数_08

 

6. vector<bool>

读书笔记之:More Exceptional C++ (2002) [++]_函数指针_09

7. vector和deque

读书笔记之:More Exceptional C++ (2002) [++]_#include_10

读书笔记之:More Exceptional C++ (2002) [++]_函数指针_11

读书笔记之:More Exceptional C++ (2002) [++]_模板函数_12

调用reserve()永远不会缩小vector的容量,调用reserve()只能增加容量,或者,如果容量已经足够,他就什么事都不做。

将vector缩小到合适大小的正确方法

读书笔记之:More Exceptional C++ (2002) [++]_ios_13

读书笔记之:More Exceptional C++ (2002) [++]_函数指针_14

 

8. set和map

map中的键值对是不能修改的,下面的方式可能修改成功,但是会破坏map的结构:

读书笔记之:More Exceptional C++ (2002) [++]_ios_15

如果要修改键值的话,可以采用先删除再插入的方式。

读书笔记之:More Exceptional C++ (2002) [++]_ios_16

 

9. 等同的代码吗?

(1) 下面的代码做了些什么?

//例9-1

f(a++);

请回答得尽可能的完整,涵盖所有的可能性。

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_17

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_18

 

(2)下面两段代码有区别吗?

//例9-2(a)

f(a++);

//例9-2(b)

f(a);

a++;

读书笔记之:More Exceptional C++ (2002) [++]_#include_19

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_20

10. 模板特化与函数重载

非模板函数总是优于模板函数,但是非模板函数只有在完全匹配的时候才会被优先选用

11. 内联函数inline

内联函数一定会提高效率吗?

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_21

12. 零长度数组是合法的

读书笔记之:More Exceptional C++ (2002) [++]_#include_22

13. 写一个可以返回自己函数指针的函数

读书笔记之:More Exceptional C++ (2002) [++]_函数对象_23

读书笔记之:More Exceptional C++ (2002) [++]_ios_24

读书笔记之:More Exceptional C++ (2002) [++]_#include_25

 

14. 直接初始化与复制初始化

读书笔记之:More Exceptional C++ (2002) [++]_ios_26