C++ primer plus第15-16章笔记

第15章

  • 友元类可以声明在公有,私有,保护任意部分。
class Tv
{
public:
    friend class Remote; 
......
}
class Remote
{
.....
}

这样Remote可以使用Tv的私有成员。

class Tv;                       // forward declaration

class Remote
{
.....
}
class Tv
{
public:
    friend void Remote::set_chan(Tv & t, int c);
.....
}

这样只有Remote::set_chan(Tv & t, int c)成为了友元方法。

  • 注意互为友元的时候,对于使用Remote对象的Tv方法,其原型可在Remote类声明之前声明,但必须在Remote类声明之后定义。

  • 嵌套类

声明位置 包含它的类是否可以使用它 从包含它的类派生而来的类是否可以使用它 在外部是否可以使用
私有部分
保护部分
公有部分 是,通过类限定符来使用
  • 调用abort()函数可以终止程序(包含头文件cstdlib)

  • throw关键字表示引发异常,紧随其后的值指出了异常的特征。

  • C++通常通过将信息放在栈中来处理函数调用,普通函数程序会将函数指令的地址(返回地址)放到栈中,执行完毕后,程序再确定从哪开始执行。然而,函数异常终止之后,程序也将释放栈中的内存,但不会再释放栈的第一个返回地址后停止,而是继续释放栈,直至找到一个位于try块中的返回地址。然后控制权转到块尾的异常处理程序。

  • exception类

    • stdexcept异常类:分为logic_error和runtime_error类
      logic_error包括domain_error, invalid_argument, length_error, out_ot_bounds
      runtime_error包括range_error, overflow_error, underflow_error
    • bad_alloc异常:
      在头文件new中。在new请求内存出现分配问题时触发。
    • C++提供了一种在失败时返回空指针的new。用法:int * pi = new (std::nothrow) int;或者int *pa = new (std::nowthrow) int[500]
  • 异常同样可以继承。程序15.14,书634页的例子。

  • 未捕获异常不会导致程序立刻异常终止,程序会先调用terminate(),默认情况下,terminate()会调用abort()。可以调用set_terminate()函数来修改terminate()的行为。
    如果发生意外异常,会调用unexpected()函数,默认调用abort(),同样可以使用set_unexpected()函数来修改行为。

  • RTTI(运行阶段类型识别)

    • dynamic_cast运算符
      可以确定转换是否安全,例如:Superb* pm = dynamic_cast(pg)。如果能安全转换则返回对象的地址,否则返回一个空指针。
    • typeid运算符用于确定两个对象是否为同种类型。typeid(Megnificent) == typeid(*pg)如果pg是空指针,则会引发bad_typeid异常。
  • 类型转换符:

    • dynamic_cast在类层次结构中进行向上转换。
    • const_cast只能用于改变值为const或volatile
    • static_cast当转换的类型是原类型所属的类型时才可以使用。
    • reinterpret_cast用于底层编程,一般用不到。

第16章

  • string类的构造函数
    1.string(const char * s)
    说明:将string对象初始化为s指向NBTS。NBTS为null-byte-temnated string的缩写,表示以空字符结束的字符串——传统的C字符串。
    2.string(size_type n,char c)
    说明:创建一个包含n个元素的string对象,其中每个元素都被初始化为字符c
    3.string(const string & str,string size_type n = npos)
    说明:将string对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos开始的n个字符
    4.string()
    说明:创建一个的string对象,长度为0
    5.string(const char * s, size_type n)
    说明:将string对象初始化为s指向的NBTS中的前n字符,即使超过了NBTS端
    6.template< clas Iter > string(Iter begin,Iter end)
    说明:将string对象初始化为区间[begin,end]内的字符,其中begin和end的行为就像指针,用于指定位置,范围包括begin在内,但不包括end
    7.string(const string & str, string size_type pos = 0, size_type n = npos)
    将string对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos开始的n个字符。
    8.string(string && str) noexcept
    将一个string对象初始化为string对象的str,并可能修改str
    9.string(initializer_list< char > il)
    将一个string对象初始化为初始化列表il中的字符
    注意:区间是包前不包后。

  • string类的输入:

string stuff;
cin>> stuff;
getline(cin, stuff);
getline(stuff, ':');

char info[100];
cin>>info;
cin.getline(info,100);
cin.get(info, 100);
cin.getline(info,100,':');
  • string类的find方法:
    原型如下:
    (1)size_t find (const string& str, size_t pos = 0) const; //查找对象–string类对象
    (2)size_t find (const char* s, size_t pos = 0) const; //查找对象–字符串
    (3)size_t find (const char* s, size_t pos, size_t n) const; //查找对象–字符串的前n个字符
    (4)size_t find (char c, size_t pos = 0) const; //查找对象–字符
    结果:找到 – 返回 第一个字符的索引;没找到–返回 string::npos。

  • capacity()返回当前分配给字符串的内存块的大小,函数reserve()将字符串的容量设置为至少size. 如果size指定的数值要小于当前字符串中的字符数(亦即size < this→size()), 容量将被设置为可以恰好容纳字符的数值。最大的用处是为了避免反复重新分配缓冲区内存而导致效率降低,或者在使用某些STL操作(例如std::copy)之前保证缓冲区够大。

  • 智能指针:过期内存自动释放。

    • 内存指针必须显式转换,不能隐式转换,例如:
      shared_ptr pd;
      double *p = new double;
      pd = p; //错误写法,隐式转换
      pd = shared_ptr(p); // 显式转换

    • 注意不能让智能指针指向同一个对象,因为这样会删除一个对象两次。为了解决, auto_ptr和unique_ptr采用的是所有权概念,shared_ptr使用的是引用计数的方法。

    • 如果程序将unique_ptr赋给另外一个,在unique_ptr只作为一个临时右值时是允许的,但是如果要存在一段时间,不允许。
    • 使用new分配内存时,才能使用auto_ptr和shared_ptr,不能使用new []。unique_ptr有new和new[]的版本。
STL
  • 模板类vector代替数组,在< type >中声明数组中的类型,变量名后用括号()指明数组元素个数。有
函数 作用
swap() 交换
begin() 返回第一个元素的迭代器
end() 返回最后一个元素的迭代器
push_back() 将元素添加到队尾,并自动加长长度
erase() 有两个迭代器参数,删除指定区间的元素
insert() 三个参数,第一个参数是插入的位置,后两个是插入区间
  • 迭代器:广义指针,可以是指针,也可以是对其执行类似指针的操作。声明:vector::iterator pd可执行类似指针的操作。
pd = scores.begin();
*pd = 2;
++pd;
  • 超过结尾:一种迭代器,指向容器的最后一个元素后面的那个元素。

  • STL函数:

函数 作用
for_each() 函数指向容器每个元素,但是不能改变值
Random_shuffle() 有两个迭代器参数,随机排列区间内的元素
sort() 排序

- 迭代器类型:输入,输出,正向,双向,随机访问迭代器。

  • 固定时间和线性时间复杂度

  • 七种主要容器:

    • vector(前面已经介绍过)
    • deque表示双端队列,从开始位置插入和删除元素时间固定。
    • list表示双向链表,任意位置插入和删除时间固定,但是不能随机访问。其成员函数:
      assign() 给list赋值
      back() 返回最后一个元素
      begin() 返回指向第一个元素的迭代器
      clear() 删除所有元素
      empty() 如果list是空的则返回true
      end() 返回末尾的迭代器
      erase() 删除一个元素
      front() 返回第一个元素
      get_allocator() 返回list的配置器
      insert() 插入一个元素到list中
      max_size() 返回list能容纳的最大元素数量
      merge() 合并两个list
      pop_back() 删除最后一个元素
      pop_front() 删除第一个元素
      push_back() 在list的末尾添加一个元素
      push_front() 在list的头部添加一个元素
      rbegin() 返回指向第一个元素的逆向迭代器
      remove() 从list删除元素
      remove_if() 按指定条件删除元素
      rend() 指向list末尾的逆向迭代器
      resize() 改变list的大小
      reverse() 把list的元素倒转
      size() 返回list中的元素个数
      sort() 给list排序
      splice() 合并两个list
      swap() 交换两个list
      unique() 删除list中重复的元素
    • forward_list表示单链表,只需正向迭代器,不可反转。
    • queue是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构。操作函数:
      back()返回最后一个元素
      empty()如果队列空则返回真
      front()返回第一个元素
      pop()删除第一个元素
      push()在末尾加入一个元素
      size()返回队列中元素的个数
    • priority_queue操作和queue相同,最大的元素被移到队首。
    • stack表示栈,操作:
      1.入栈:如s.push(x);
      2.出栈:如 s.pop().注意:出栈操作只是删除栈顶的元素,并不返回该元素。
      3.访问栈顶:如s.top();
      4.判断栈空:如s.empty().当栈空时返回true。
    • array
  • 关联容器:值和键关联在一起。

    • set:关联集合,可反转,排序,键值唯一,不能存储多个相同的值。例如:set a
      模板第二个参数可选,可以是对键进行排序的比较函数或对象。默认有默认值。
      常用操作:
      1.元素插入:insert()
      2.中序遍历:类似vector遍历(用迭代器)
      3.反向遍历:利用反向迭代器reverse_iterator。
      例:
      set< int> s;
      ……
      set< int>::reverse_iterator rit;
      for(rit=s.rbegin();rit!=s.rend();rit++)
      4.元素删除:与插入一样,可以高效的删除,并自动调整使红黑树平衡。
      set< int> s;
      s.erase(2); //删除键值为2的元素
      s.clear();
      5.元素检索:find(),若找到,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置。
      set< int> s;
      set< int>::iterator it;
      it=s.find(5); //查找键值为5的元素
      if(it!=s.end()) //找到
      cout<<*it << endl;
      else //未找到
      cout<<”未找到”;
      6.自定义比较函数
      (1)元素不是结构体:
      例:
      //自定义比较函数myComp,重载“()”操作符
      struct myComp
      {
      bool operator()(const your_type &a,const your_type &b)
      [
      return a.data-b.data > 0;
      }
      }
      set< int,myComp>s;
      ……
      set< int,myComp>::iterator it;
      (2)如果元素是结构体,可以直接将比较函数写在结构体内。
      例:
      struct Info
      {
      string name;
      float score;
      //重载“<”操作符,自定义排序规则
      bool operator < (const Info &a) const
      {
      //按score从大到小排列
      return a.score < score;
      }
      }
      set< Info> s;
      ……
      set< Info>::iterator it;
    • multimap:可反转,经过排序的关联容器,但键和值的类型不同,且同一个键可能与多个值相关联。
      基本操作:
begin() 返回指向第一个元素的迭代器
clear() 删除所有元素
count() 返回一个元素出现的次数
empty() 如果multimap为空则返回真
end() 返回一个指向multimap末尾的迭代器
equal_range() 返回指向元素的key为指定值的迭代器对
erase() 删除元素
find() 查找元素
get_allocator() 返回multimap的配置器
insert() 插入元素
key_comp() 返回比较key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向mulitmap尾部的逆向迭代器
rend() 返回一个指向multimap头部的逆向迭代器
size() 返回multimap中元素的个数
swap() 交换两个multimaps
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数

你可能感兴趣的:(C++)