SGI的basic_string的代码分析

来源:互联网 发布:金融数据服务商排名 编辑:程序博客网 时间:2024/05/19 17:23

// 首先必须要了解的就是char_traits

#include <cstddef>

// 下面是string_char_traits,至于traits的好处,c-view的杂志里面已经有所描述
// TCPL里面也有描述
extern "C++" {
template <class charT>
struct string_char_traits {
  typedef charT char_type; // for users to acquire the basic character type

  // constraints,这些都是模板偏特化必须提供的
  static void assign (char_type& c1, const char_type& c2)
    { c1 = c2; }  // 给c1赋值 ,要求charT必须支持operator =()
  static bool eq (const char_type& c1, const char_type& c2)
    { return (c1 == c2); } //返回c1是否eaqual c2 要求charT必须支持operator ==()
  static bool ne (const char_type& c1, const char_type& c2)
    { return !(c1 == c2); } // not eaqual ,要求charT必须支持operator ==()
  static bool lt (const char_type& c1, const char_type& c2)
    { return (c1 < c2); } // lower than,要求charT必须支持operator <()
  static char_type eos () { return char_type(); }
  // the null character ,注意 下面用char偏特化的时候,使用的是retuun 0
 
  static bool is_del(char_type a) { return 0; }

  // characteristic function for delimiters of charT
 
  static int compare (const char_type* s1, const char_type* s2, size_t n)
    {
      size_t i;
      for (i = 0; i < n; ++i)
 if (ne (s1[i], s2[i]))
   return lt (s1[i], s2[i]) ? -1 : 1;
      return 0;
    } // 比较s1,s2这两个指针开始的长度为n的字符串的大小,这里直接利用上面定义的成员函数完成的
   // 当用char作为模板参数的时候,则是直接利用的memcmp, :)
   
  static size_t length (const char_type* s) // 返回s的长度,以eos()表示字符串的结束,
    {
      size_t l = 0;
      while (ne (*s++, eos ()))
 ++l;
      return l;
    }

  static char_type* copy (char_type* s1, const char_type* s2, size_t n)
    {
      for (; n--; )
 assign (s1[n], s2[n]);
      return s1;
    } //拷贝字符串,这里使用的是循环完成任务的,注意和偏特化方案的比较!

  static char_type* move (char_type* s1, const char_type* s2, size_t n)
    {
      char_type a[n];
      size_t i;
      for (i = 0; i < n; ++i)
 assign (a[i], s2[i]);
      for (i = 0; i < n; ++i)
 assign (s1[i], a[i]);
      return s1;
    } // 需要澄清的两点是:
   // 1)move 并不是简单的“搬动”,s2里面的内容没有必要置NULL
      // 为何不直接象copy一样,一次循环assign完成哪?不要奇怪,可以下面memcpy,memmove的比较

  static char_type* set (char_type* s1, const char_type& c, size_t n)
    {
      for (; n--; )
 assign (s1[n], c);
      return s1;
    } // 将s1开始的n个字符都赋值为c
};

class istream;  // 这里仅仅是declare, 不是definition,可以多次declare,
class ostream;
#include <cctype>
#include <cstring>

struct string_char_traits <char> {  // 对string_cahr_traits进行偏特化
  typedef char char_type;

  static void assign (char_type& c1, const char_type& c2)
    { c1 = c2; }
  static bool eq (const char_type & c1, const char_type& c2)
    { return (c1 == c2); }
  static bool ne (const char_type& c1, const char_type& c2)
    { return (c1 != c2); }
  static bool lt (const char_type& c1, const char_type& c2)
    { return (c1 < c2); }
  static char_type eos () { return 0; }
  static bool is_del(char_type a) { return isspace(a); }

  static int compare (const char_type* s1, const char_type* s2, size_t n)
    { return memcmp (s1, s2, n); }
  static size_t length (const char_type* s)
    { return strlen (s); }
  static char_type* copy (char_type* s1, const char_type* s2, size_t n)
    { return (char_type*) memcpy (s1, s2, n); }
  // The memcpy function copies count bytes of src to dest.
  // If the source and destination overlap,
  // this function does not ensure that the original source bytes in the overlapping region are copied
  // before being overwritten.  Use memmove to handle overlapping regions.

  static char_type* move (char_type* s1, const char_type* s2, size_t n)
    { return (char_type*) memmove (s1, s2, n); }
  // The memmove function copies count bytes of characters from src to dest.
  // If some regions of the source area and the destination overlap,
  // memmove ensures that the original source bytes in the overlapping region are copied before being overwritten
  static char_type* set (char_type* s1, const char_type& c, size_t n)
    { return (char_type*) memset (s1, c, n); }
};

 
#include <cwctype>
struct string_char_traits <wchar_t> {
  typedef wchar_t char_type;

  static void assign (char_type& c1, const char_type& c2)
    { c1 = c2; }
  static bool eq (const char_type & c1, const char_type& c2)
    { return (c1 == c2); }
  static bool ne (const char_type& c1, const char_type& c2)
    { return (c1 != c2); }
  static bool lt (const char_type& c1, const char_type& c2)
    { return (c1 < c2); }
  static char_type eos () { return 0; }
  static bool is_del(char_type a) { return iswspace(a); }

  static int compare (const char_type* s1, const char_type* s2, size_t n)
    { return wmemcmp (s1, s2, n); }
  static size_t length (const char_type* s)
    { return wcslen (s); }
  static char_type* copy (char_type* s1, const char_type* s2, size_t n)
    { return wmemcpy (s1, s2, n); }
  static char_type* set (char_type* s1, const char_type& c, size_t n)
    { return wmemset (s1, c, n); }
};
 
} // extern "C++"

extern void __out_of_range (const char *);
extern void __length_error (const char *);
#define OUTOFRANGE(cond) /
  do { if (cond) __out_of_range (#cond); } while (0)
#define LENGTHERROR(cond) /
  do { if (cond) __length_error (#cond); } while (0)
// 注意这里的 “#cond” 这个 很有意思的用法, 看看下面这个用法 就知道了!
// #define print(arg)  cout<<#arg " = "<<arg
// int main()
// {   int a=1;
//     print(a); }
// 可惜的是,怎么着都没有能够找到 __out_of_ranget(const char *) 此函数的定义所在!
// 整个OUTOFRANGE(cond) 这个宏的作用是 :判断cond条件,如果cond为真,
// 那么就调用__out_of_range(const char*)
// 而在此函数里面 则抛出一个异常! 估计带入的“#cond”就保存在该异常的内部,可以打印出来!
// LENGTHERROR(cond)宏的作用 和 OUTOFRANGE(cond)宏类似!

// 奇怪的是,这里的 do { } while(0) 的用法,有点匪夷所思!
// 除非带入的宏参数cond是一个复杂的“字符串”,cond其中含有“}” ,这样和"do { "恰好匹配
// 否则, 这里就相当于 “if (cond) __out_of_range (#cond);”
// do {} while(0) 根本起不到作用!

 
// basic_string 使用了 “引用计数”来实现string,这样可以减少内存分配的次数!
// 可以参考More effective Item 29
// 我们先来看basic_string的内部数据成员,仅仅包含两个
// 1)static Rep nilRep; //  初始化为 {0, 0, 1, false}
// 2)charT *dat;  // 真正存放字符串(charT)的地方,动态allocate
// 乍一看上去,nilRep被定义成static,这和我们平时所看到的reference count很不相同
// 既然已经被定义成static数据成员,那么就会被basic_string<charT ...>的所有对象所共有
// 怎么还能用于reference count哪? 因为reference count里面的计数器只是针对具有相同“数据”的对象计数!
// 这里的nilRep的作用是 :对Empty string 进行计数!
// 而具有“真正有效数据的对象” 则 使用 另外一个 “隐式”的Rep对象进行计数
// 为什么,这里的Rep对象是“隐式”的哪? 因为该对象从始至终都没有一个自己的名字
// 在使用到此对象的时候都是使用 “reinterpret_cast” ,再加上内存地址运算 完成的,
// 可以看basic_string::Rep::data(),new(),delete(), create()等等!
// 我们就先参考basic_string::Rep::create(),大致了解一下basic_string的内部数据的安排情况!

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>::Rep *
basic_string <charT, traits, Allocator>::Rep::
create (size_t extra)
{
  extra = frob_size (extra + 1);  // 这里经过计算得到一个比较适中的长度,后面再看
  Rep *p = new (extra) Rep; // 这里刚看上去 好像适 new placement! 其实不是 :(
     // new placement 的new定义为: void* operator new(size_t, void* pMem) { return pMem; }
     // 你看到后面的这里的new的定义 ,你就会知道,其实这里是调用自己的new( sizeof(Rep), extra )
  // 看到这个,你会发现 :在给字符串分配内存的时候,basic_string给你偷偷的添加了一个 “头”
  //  这个头用于 记录该字符串的一系列信息! 但是这个头没有名字,所以一切的操作都不得不通过地址运算完成!
  p->res = extra;             
  p->ref = 1;              // 这三行都是给这个头信息自己的内部数据初始化!
  p->selfish = false;                      
  return p;
}

template <class charT, class traits, class Allocator>
inline void * basic_string <charT, traits, Allocator>::Rep::
operator new (size_t s, size_t extra)
{
  return Allocator::allocate(s + extra * sizeof (charT));
  //分配长度为 (sizeof(Rep)+实际字符串的capacity )的内存!
}

//知道了basic_string的内存模型,我们就可以来分析basic_string 的相关源代码了!

// 下面开始分析basic_string::Rep的结构!在了解了basic_string::Rep的结果之后,才能更好的明白basic_string的实现!

 template <class charT, class traits = string_char_traits<charT>,
   class Allocator = alloc >
class basic_string
{
private:
 //  下面的struct Rep 是 basic_string的内部类Rep的定义,
  struct Rep {
    size_t len, res, ref;
     // len --Rep 内部的有效数据的长度! --在basic_string::length()里面会表现出来
  // res --分配的内存长度            --在basic_string::capacity()里面会表现出来
  // ref -- reference count
    bool selfish;  // 用于标记 是否为私有!

    charT* data () { return reinterpret_cast<charT *>(this + 1); }
    // 注意这里的操作,这里(this +1)之后的地址,也就是字符串真正开始的地方--首地址!
    // this+1 这个操作 相当于 &(*this)+sizeof(Rep)
    charT& operator[] (size_t s) { return data () [s]; }
    // 知道了字符串的首地址,求的第s个字符所在的地址
    charT* grab () { if (selfish) return clone (); ++ref; return data (); }
    // 大致的作用:如果selfish(完全私有),那么就拷贝一份返回
    // 否则 直接将自己内部的字符串的首地址返回, 修改引用计数值
     void release () { if (--ref == 0) delete this; } 
    // 这个和 普通引用计数里面的 用法一直,release的过程中,修改引用计数,如果没有引用了,那么释放内存

    inline static void * operator new (size_t, size_t);
    inline static void operator delete (void *);
    inline static Rep* create (size_t); // 分配内存,参数为字符串实际占有的个数
    charT* clone (); // 拷贝字符串

    inline void copy (size_t, const charT *, size_t); // 分配新内存,拷贝字符串
    inline void move (size_t, const charT *, size_t);
    inline void set  (size_t, const charT,   size_t);

    inline static bool excess_slop (size_t, size_t);
    inline static size_t frob_size (size_t);  // 计算

 //  在后面!
  private:
    Rep &operator= (const Rep &);   // 禁止operator=
  };
};
  //  end of the Rep's Declaring


/// #include <std/bastring.cc>
//  basic_string::Rep 的内部成员函数的定义

extern "C++" {
template <class charT, class traits, class Allocator>
inline void * basic_string <charT, traits, Allocator>::Rep::
operator new (size_t s, size_t extra)
{
  return Allocator::allocate(s + extra * sizeof (charT));
} // 调用Allocator 分配内存, 这里的两个参数
  // basic_string内部包含一个Rep指针对象,用于存储相关的一系列数据,另外还有用于存放char数组的对象
  // s -- sizeof(Rep) , extra --basic_string 里面char数据的长度!
  // 所以整个sizeof(basic_string)应该是 Rep的大小
  // 将basic_string::Rep::operator new()和 basic_string::Rep::create 结合起来考察!

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
operator delete (void * ptr)
{
  Allocator::deallocate(ptr, sizeof(Rep) +
   reinterpret_cast<Rep *>(ptr)->res *
   sizeof (charT)); // 了解了res的作用,也就明白这里的表达式
                             // res存放分配的字符串的个数,相当于basic_string::capacity()
}

template <class charT, class traits, class Allocator>
inline size_t basic_string <charT, traits, Allocator>::Rep::
frob_size (size_t s)
{
  size_t i = 16;
  while (i < s) i *= 2;
  return i;
} // 为了和计算机的内存模型更匹配,这里计算得到实际分配的内存大小!
  // 这里也就是如何计算字符串内存分配大小的策略!

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>::Rep *
basic_string <charT, traits, Allocator>::Rep::
create (size_t extra)
{
  extra = frob_size (extra + 1); // 计算实际分配的内存大小
  Rep *p = new (extra) Rep; // Rep::operator new(), not placement!
                            // Rep的默认构造函数会 初始化len=0
  p->res = extra;  //存放内存实际大小!
  p->ref = 1;
  p->selfish = false;
  return p;
}

template <class charT, class traits, class Allocator>
charT * basic_string <charT, traits, Allocator>::Rep::
clone ()
{
  Rep *p = Rep::create (len); // 重新分配内存 ,这时候也就给新分配的内存添加“隐式”头--Rep
  p->copy (0, data (), len); // 拷贝字符串
  p->len = len;
  return p->data ();
}

template <class charT, class traits, class Allocator>
inline bool basic_string <charT, traits, Allocator>::Rep::
excess_slop (size_t s, size_t r)
{
  return 2 * (s <= 16 ? 16 : s) < r;
} // 和frob_size相似,这里仅仅判断s是否满足要求:参考Rep::frob_size

template <class charT, class traits, class Allocator>
inline bool basic_string <charT, traits, Allocator>::
check_realloc (basic_string::size_type s) const
{
  s += sizeof (charT);
  rep ()->selfish = false;
  return (rep ()->ref > 1
   || s > capacity ()
   || Rep::excess_slop (s, capacity ()));
   // 这三者为是否有必要重新分配内存的必要条件
}

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
copy (size_t pos, const charT *s, size_t n)
{
  if (n)
   traits::copy (data () + pos, s, n); // 这里利用到了char_traits, 会在后面提及
} // 将s的内容拷贝至this

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
move (size_t pos, const charT *s, size_t n)
{
  if (n)
    traits::move (data () + pos, s, n);
} // 将s的内容移动至this

template <class charT, class traits, class Allocator>
inline void basic_string <charT, traits, Allocator>::Rep::
set (size_t pos, const charT c, size_t n)
{
  traits::set  (data () + pos, c, n);
} // 将字符串中从pos开始的n个字符设置为字符c ,

// basic_string::Rep 分析结束!



真正的basic_String 开始 :


extern "C++" {
class istream; class ostream;


template <class charT, class traits = string_char_traits<charT>,
   class Allocator = alloc >
class basic_string
{
public:
// types:
  typedef    traits  traits_type;
  typedef typename traits::char_type value_type;
  typedef    Allocator  allocator_type;

//  下面的这些类型定义 是为了满足算法的要求,有了这些定义,string 就可以象vector一样的使用!
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef charT& reference;
  typedef const charT& const_reference;
  typedef charT* pointer;
  typedef const charT* const_pointer;
  typedef pointer iterator;
  typedef const_pointer const_iterator;
  typedef ::reverse_iterator<iterator> reverse_iterator;  // ::运算符的作用
  typedef ::reverse_iterator<const_iterator> const_reverse_iterator;
 
// 下面是basic_string的内部数据成员的定义
  static const size_type npos = static_cast<size_type>(-1);
    // 这里直接给出定义static变量,但是在class的外面,还需要declare一次
 // 你也可以在class 里面declare,在外面definition
   // npos 指
private:
  static Rep nilRep; //  在class外面被初始化为 {0, 0, 1, false}
  charT *dat;  // 真正存放字符串(charT)的地方,动态allocate  

private:
  Rep *  rep () const { return reinterpret_cast<Rep *>(dat) - 1; }
    // 得到指向内部Rep对象(用于存放真正意义的字符串)的指针!
 // 因为basic_string::dat 指向的是字符串真正开始的地方,
 // 在this被强行转换为Rep*后,再-1,这时候的指针 就指向前面“隐式”的Rep对象了!
  void repup (Rep *p) { rep ()->release (); dat = p->data (); }
    // 这里看起来作用是 “给basic_string内部存放数据的dat重新赋值!”
 // 所以整个的动作分为两步 : 1) 先release()原来自己的用的 2)再重新赋值
 // 当然了,这时候会在适当的地方修改 “引用计数” !

public:
  const charT* data () const
    { return rep ()->data(); } // 这里可以改为直接return dat ;
  size_type length () const
    { return rep ()->len; } // rep()得到字符串前面的隐式的Rep头,里面保存了该字符串的一系列的内部信息!
  size_type size () const
    { return rep ()->len; }
  size_type capacity () const
    { return rep ()->res; } // 看到这里returnrep()->res; 也可以说明Rep::res的作用是记录字符串所占有的内存长度
  size_type max_size () const
    { return (npos - 1)/sizeof (charT); }  // XXX
    // npos 就是 ( unsigned int) -1 , max_size 就是返回系统能够分配的最大字符(charT)数组的长度

  bool empty () const
    { return size () == 0; }

// _lib.string.cons_ construct/copy/destroy:
  basic_string& operator= (const basic_string& str)
    {
      if (&str != this) { rep ()->release (); dat = str.rep ()->grab (); }
      return *this;
    } // operator::=()必须要检验“自赋值”
   // 第一步,肯定是release自己原来占有的了
      // 第二步,赋予新的值,新的值可能是str的copy,也可能和str共有同一字符串,这是由Rep::grab()完成的!

  explicit basic_string (): dat ( nilRep.grab () ) { }
     // 不带任何参数的basic_string的构造函数,这里使用的是nilRep.grab()
  // 可以看到空字符串是被单独处理的,他们都共同引用basic_string::nilRep.
  // 而不是象其他非空字符串一样,先创建一个空字符串,然后大家再共同引用这个空字符串!

  basic_string (const basic_string& str): dat ( str.rep ()->grab ()) { }
     // copy-cotr! 和operator::=() 相似! 但是不需要再考虑自赋值

  basic_string (const basic_string& str, size_type pos, size_type n = npos)
    : dat (nilRep.grab ()) { assign (str, pos, n); }
  basic_string (const charT* s, size_type n)
    : dat (nilRep.grab ()) { assign (s, n); }
  basic_string (const charT* s)
    : dat (nilRep.grab ()) { assign (s); }
  basic_string (size_type n, charT c)
    : dat (nilRep.grab ()) { assign (n, c); }
  template<class InputIterator>
    basic_string(InputIterator begin, InputIterator end)
     : dat (nilRep.grab ()) { assign (begin, end); }
     // 以上几个构造函数,不错! :)  思路经典!一切都集中到了assign 成员函数上

  ~basic_string ()
    { rep ()->release (); } // 所有的认为(判断计数,释放内存)都由Rep::release()完成

  void swap (basic_string &s) { charT *d = dat; dat = s.dat; s.dat = d; }
  //  :)

  basic_string& append (const basic_string& str, size_type pos = 0,
   size_type n = npos)
    { return replace (length (), 0, str, pos, n); }
  basic_string& append (const charT* s, size_type n)
    { return replace (length (), 0, s, n); }
  basic_string& append (const charT* s)
    { return append (s, traits::length (s)); }
  basic_string& append (size_type n, charT c)
    { return replace (length (), 0, n, c); }
   template<class InputIterator>
    basic_string& append(InputIterator first, InputIterator last)
     { return replace (iend (), iend (), first, last); }
  // append的工作都用replace完成!

  basic_string& assign (const basic_string& str, size_type pos = 0,
   size_type n = npos)
    { return replace (0, npos, str, pos, n); }
  basic_string& assign (const charT* s, size_type n)
    { return replace (0, npos, s, n); }
  basic_string& assign (const charT* s)
    { return assign (s, traits::length (s)); }
  basic_string& assign (size_type n, charT c)
    { return replace (0, npos, n, c); }
  template<class InputIterator>
    basic_string& assign(InputIterator first, InputIterator last)
    { return replace (ibegin (), iend (), first, last); }
  // assign 也由replace完成了

  basic_string& operator= (const charT* s)
    { return assign (s); }
  basic_string& operator= (charT c)
    { return assign (1, c); }
  // 这个算是对operator =()的重载了

  basic_string& operator+= (const basic_string& rhs)
    { return append (rhs); }
  basic_string& operator+= (const charT* s)
    { return append (s); }
  basic_string& operator+= (charT c)
    { return append (1, c); }

  basic_string& insert (size_type pos1, const basic_string& str,
   size_type pos2 = 0, size_type n = npos)
    { return replace (pos1, 0, str, pos2, n); }
  basic_string& insert (size_type pos, const charT* s, size_type n)
    { return replace (pos, 0, s, n); }
  basic_string& insert (size_type pos, const charT* s)
    { return insert (pos, s, traits::length (s)); }
  basic_string& insert (size_type pos, size_type n, charT c)
    { return replace (pos, 0, n, c); }
  iterator insert(iterator p, charT c)
    { size_type __o = p - ibegin ();
      insert (p - ibegin (), 1, c); selfish ();
      return ibegin () + __o; }
  iterator insert(iterator p, size_type n, charT c)
    { size_type __o = p - ibegin ();
      insert (p - ibegin (), n, c); selfish ();
      return ibegin () + __o; }
   template<class InputIterator>
    void insert(iterator p, InputIterator first, InputIterator last)
     { replace (p, p, first, last); }
   // insert 也由 replace完成

  basic_string& erase (size_type pos = 0, size_type n = npos)
    { return replace (pos, n, (size_type)0, (charT)0); }
  iterator erase(iterator p)
    { size_type __o = p - begin();
      replace (__o, 1, (size_type)0, (charT)0); selfish ();
      return ibegin() + __o; }
  iterator erase(iterator f, iterator l)
    { size_type __o = f - ibegin();
      replace (__o, l-f, (size_type)0, (charT)0);selfish ();
      return ibegin() + __o; }
   // erase也是  :(

  basic_string& replace (size_type pos1, size_type n1, const basic_string& str,
    size_type pos2 = 0, size_type n2 = npos);
  basic_string& replace (size_type pos, size_type n1, const charT* s,
    size_type n2);  // declare,会在class之外给出定义

  basic_string& replace (size_type pos, size_type n1, const charT* s)
    { return replace (pos, n1, s, traits::length (s)); }
  basic_string& replace (size_type pos, size_type n1, size_type n2, charT c);
  basic_string& replace (size_type pos, size_type n, charT c)
    { return replace (pos, n, 1, c); }
  basic_string& replace (iterator i1, iterator i2, const basic_string& str)
    { return replace (i1 - ibegin (), i2 - i1, str); }
  basic_string& replace (iterator i1, iterator i2, const charT* s, size_type n)
 
private:
  static charT eos () { return traits::eos (); } // 字符串的结束标记,由char_traits给出各自的定义

  // unique,selfish,operator []的配合使用,这里并没有使用proxy类(参考More Eff)
  void unique () { if (rep ()->ref > 1) alloc (length (), true); }
  // unique的作用:使自己不再和别人共有字符串数据,不得已的情况下,自己重新分配内存,将数据拷贝过来!
  void selfish () { unique (); rep ()->selfish = true; }
 
public:
  charT operator[] (size_type pos) const
    {
      if (pos == length ())
 return eos ();
      return data ()[pos];  // 根本没有判断越界,因为这里是const成员函数,不会修改内部数据,所以不要selfish
    }

  reference operator[] (size_type pos)
    { selfish ();  //这里就不同了,害怕修改内部数据,所以必须事先做好准备,selfish!不再和别人共有数据了!
      return (*rep ())[pos];
   } // 这里的return 也可以和上面的一样写,return data()[pos],查看 Rep:operator[] 就知道了!

  reference at (size_type pos)
    {
      OUTOFRANGE (pos >= length ());  // 判断是否越界! 会抛出异常!
      return (*this)[pos]; // 这个用起basic_string:operator[]了! 呵呵!
    // 在basic_string::operaotor[]里面做了selfish的工作,不要奇怪 :)
    }
  const_reference at (size_type pos) const // 这个是专门为const basic_string使用的!
    {
      OUTOFRANGE (pos >= length ());
      return data ()[pos];
    }

private:
  void terminate () const
    { traits::assign ( (  *rep () )[length ()],  eos () ); }
  // 给字符串加了一个“结尾符”! 原来在basic_string的构造函数里面(在此里面利用的是replace)是没有结尾符的!
  // 这里加上结尾符,为转换为CString做准备!
  // 注意:basic_string内部字符串的有效范围是[0,length)
  // 这里仅仅是在字符串的外面修改了一个“本来随机”的字符串为“结尾符”,
  // 并没有修改原本有效的数据,也没有修改字符串的有效长度!

public:
  const charT* c_str () const
    { if (length () == 0) return ""; terminate (); return data (); }
  // 利用了terminate! 因为c_str是const成员函数,不会修改内部数据!

  void resize (size_type n, charT c);  // 在后面给出定义!
  void resize (size_type n)
    { resize (n, eos ()); }
  // 呵呵,所以这时候如果参数n>length(), 那么,有效字符串的后面就会有着“结尾符”!
  // 那么cout<<basic_string::c_str<<1<<endl和cout<<basic_string的结果就不一样啦~~
  /* # include <string>
     #include <iostream>
     int main()
     {
       string c="abc";

       cout<<c<<1<<endl;
       c.resize(5);
       cout<<c<<1<<endl;
       cout<<c.c_str()<<1<<endl;
     }   */

  void reserve (size_type) { } //  强制分配内存,可能受到影响的仅仅是basic_string::capacity(),有效字符串的长度不变!

  size_type copy (charT* s, size_type n, size_type pos = 0) const;
   // Copies a substring of *this to a buffer.

  size_type find (const basic_string& str, size_type pos = 0) const
    { return find (str.data(), pos, str.length()); }
  size_type find (const charT* s, size_type pos, size_type n) const;
  size_type find (const charT* s, size_type pos = 0) const
    { return find (s, pos, traits::length (s)); }
  size_type find (charT c, size_type pos = 0) const;
  // 正向查找

  size_type rfind (const basic_string& str, size_type pos = npos) const
    { return rfind (str.data(), pos, str.length()); }
  size_type rfind (const charT* s, size_type pos, size_type n) const;
  size_type rfind (const charT* s, size_type pos = npos) const
    { return rfind (s, pos, traits::length (s)); }
  size_type rfind (charT c, size_type pos = npos) const;
  // 反向查找

  size_type find_first_of (const basic_string& str, size_type pos = 0) const
    { return find_first_of (str.data(), pos, str.length()); }
  size_type find_first_of (const charT* s, size_type pos, size_type n) const;
  size_type find_first_of (const charT* s, size_type pos = 0) const
    { return find_first_of (s, pos, traits::length (s)); }
  size_type find_first_of (charT c, size_type pos = 0) const
    { return find (c, pos); }
  // 找正向的第一个字符(串)

  size_type find_last_of (const basic_string& str, size_type pos = npos) const
    { return find_last_of (str.data(), pos, str.length()); }
  size_type find_last_of (const charT* s, size_type pos, size_type n) const;
  size_type find_last_of (const charT* s, size_type pos = npos) const
    { return find_last_of (s, pos, traits::length (s)); }
  size_type find_last_of (charT c, size_type pos = npos) const
    { return rfind (c, pos); }
  // 找正向的最后一个字符(串),即反向的第一个字符(串)!

  size_type find_first_not_of (const basic_string& str, size_type pos = 0) const
    { return find_first_not_of (str.data(), pos, str.length()); }
  size_type find_first_not_of (const charT* s, size_type pos, size_type n) const;
  size_type find_first_not_of (const charT* s, size_type pos = 0) const
    { return find_first_not_of (s, pos, traits::length (s)); }
  size_type find_first_not_of (charT c, size_type pos = 0) const;
  // 正向找第一个字符(串)

  size_type find_last_not_of (const basic_string& str, size_type pos = npos) const
    { return find_last_not_of (str.data(), pos, str.length()); }
  size_type find_last_not_of (const charT* s, size_type pos, size_type n) const;
  size_type find_last_not_of (const charT* s, size_type pos = npos) const
    { return find_last_not_of (s, pos, traits::length (s)); }
  size_type find_last_not_of (charT c, size_type pos = npos) const;
  // 反向找第一个不适合的字符(串)

  basic_string substr (size_type pos = 0, size_type n = npos) const
    { return basic_string (*this, pos, n); }
  // 这里返回的不是引用,而是一个basic_string对象

  int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const;
  // There is no 'strncmp' equivalent for charT pointers.

  int compare (const charT* s, size_type pos, size_type n) const;
  int compare (const charT* s, size_type pos = 0) const
    { return compare (s, pos, traits::length (s)); }

  iterator begin () { selfish (); return &(*this)[0]; }
  iterator end () { selfish (); return &(*this)[length ()]; }
  // 上面两个因为返回的是iterator,可以通过iterator修改字符串的内部数据,所以实现selfish,不再和别人共享数据!
  //  这里终于不再使用rep()->data()来得到字符串数据了! 呵呵~
private:
  iterator ibegin () const { return &(*rep ())[0]; }
  iterator iend () const { return &(*rep ())[length ()]; }
 
public:
  const_iterator begin () const { return ibegin (); }
  const_iterator end () const { return iend (); }
  // const iterator,没关系,无需selfish!

  reverse_iterator       rbegin() { return reverse_iterator (end ()); }
  const_reverse_iterator rbegin() const
    { return const_reverse_iterator (end ()); }
  reverse_iterator       rend() { return reverse_iterator (begin ()); }
  const_reverse_iterator rend() const
    { return const_reverse_iterator (begin ()); }
  // 参考stl_iterator.h的分析!

private:
  void alloc (size_type size, bool save);
  static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len);
  inline bool check_realloc (size_type s) const;
  //再class外面定义!
};

// 下面两个是basic_string 的内部的static 变量!
// 其中的npos是const,所以可以在class basic_string内部就可以直接给出定义,在外面声明即可;
// 当然也可和basic_string一样;而nilRep是nonconst,所以只能在class内部declare,在class外部definition
template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::Rep
basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };

template <class charT, class traits, class Allocator>
const basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::npos;

// 非内联的basic_string的成员函数

template <class charT, class traits, class Allocator>
inline bool basic_string <charT, traits, Allocator>::
check_realloc (basic_string::size_type s) const
{
  s += sizeof (charT);
  rep ()->selfish = false;
  return (rep ()->ref > 1
   || s > capacity ()
   || Rep::excess_slop (s, capacity ()));
   // 这三者为是否有必要重新分配内存的必要条件
}

//下面的alloc 就是分配内存!,
template <class charT, class traits, class Allocator>
void basic_string <charT, traits, Allocator>::
alloc (basic_string::size_type size, bool save)
{
  if (! check_realloc (size))
    return;

  Rep *p = Rep::create (size); // 参考Rep的解释

  if (save) // 是否需要保存原来的内容?
    {
      p->copy (0, data (), length ());
      p->len = length ();
    } // 再拷贝过去,修改“隐式”头的参数,其他的参数已经再Rep::create里面设置好了!
  else
    p->len = 0;

  repup (p);
  // void repup (Rep *p) { rep ()->release (); dat = p->data (); }
  //  :)看看如何使用的吧~~
}


// 下面是basic_string::replace的内容,可以参考数据结构!
// 由于代码较长,这里删除内部的实现细节,仅仅给出 成员函数原型!
// 可以在SGI的 bastring.cc和bastring.h文件里面找到!
// 参考SGI 的文档,可以知道这里的各自的作用!
template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>&
basic_string <charT, traits, Allocator>::
replace (size_type pos1, size_type n1,
  const basic_string& str, size_type pos2, size_type n2)
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>&
basic_string <charT, traits, Allocator>::
replace (size_type pos, size_type n1, const charT* s, size_type n2)
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
replace (size_type pos, size_type n1, size_type n2, charT c)
{   }

template <class charT, class traits, class Allocator> template <class InputIterator>
basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2)
 {   }

template <class charT, class traits, class Allocator>
void basic_string <charT, traits, Allocator>::
resize (size_type n, charT c)
{
  LENGTHERROR (n > max_size ());  // 可千万别超过系统支持的最大长度 :)

  if (n > length ())
    append (n - length (), c);
  else
    erase (n);
}  // resize会修改内部数据的! 和reserve()不同~

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
copy (charT* s, size_type n, size_type pos) const
{
  OUTOFRANGE (pos > length ());

  if (n > length () - pos)
    n = length () - pos;

  traits::copy (s, data () + pos, n);
  return n;
}  // Copies a substring of *this to a buffer.

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find (const charT* s, size_type pos, size_type n) const
{    }

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
_find (const charT* ptr, charT c, size_type xpos, size_type len)
{    }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find (charT c, size_type pos) const
{
  return _find (data (), c, pos, length ());
}

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
rfind (const charT* s, size_type pos, size_type n) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
rfind (charT c, size_type pos) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_first_of (const charT* s, size_type pos, size_type n) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_last_of (const charT* s, size_type pos, size_type n) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_first_not_of (const charT* s, size_type pos, size_type n) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_first_not_of (charT c, size_type pos) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_last_not_of (const charT* s, size_type pos, size_type n) const
{   }

template <class charT, class traits, class Allocator>
basic_string <charT, traits, Allocator>::size_type
basic_string <charT, traits, Allocator>::
find_last_not_of (charT c, size_type pos) const
{   }

template <class charT, class traits, class Allocator>
int basic_string <charT, traits, Allocator>::
compare (const basic_string& str, size_type pos, size_type n) const
{    }

template <class charT, class traits, class Allocator>
int basic_string <charT, traits, Allocator>::
compare (const charT* s, size_type pos, size_type n) const
{    }

// std下的全局函数,basic_string的相关操作

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const basic_string <charT, traits, Allocator>& lhs,
    const basic_string <charT, traits, Allocator>& rhs)
{   }

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{    }

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs)
{   }

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{   }

template <class charT, class traits, class Allocator>
inline basic_string <charT, traits, Allocator>
operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs)
{   }

template <class charT, class traits, class Allocator>
inline bool
operator== (const basic_string <charT, traits, Allocator>& lhs,
     const basic_string <charT, traits, Allocator>& rhs)
{
  return (lhs.compare (rhs) == 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
  return (rhs.compare (lhs) == 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
  return (lhs.compare (rhs) == 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
  return (rhs.compare (lhs) != 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
  return (lhs.compare (rhs) != 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator< (const basic_string <charT, traits, Allocator>& lhs,
     const basic_string <charT, traits, Allocator>& rhs)
{
  return (lhs.compare (rhs) < 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
  return (rhs.compare (lhs) > 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
  return (lhs.compare (rhs) < 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
  return (rhs.compare (lhs) < 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
  return (lhs.compare (rhs) > 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
  return (rhs.compare (lhs) >= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
  return (lhs.compare (rhs) <= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
{
  return (rhs.compare (lhs) <= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
{
  return (lhs.compare (rhs) >= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator!= (const basic_string <charT, traits, Allocator>& lhs,
     const basic_string <charT, traits, Allocator>& rhs)
{
  return (lhs.compare (rhs) != 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator> (const basic_string <charT, traits, Allocator>& lhs,
    const basic_string <charT, traits, Allocator>& rhs)
{
  return (lhs.compare (rhs) > 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator<= (const basic_string <charT, traits, Allocator>& lhs,
     const basic_string <charT, traits, Allocator>& rhs)
{
  return (lhs.compare (rhs) <= 0);
}

template <class charT, class traits, class Allocator>
inline bool
operator>= (const basic_string <charT, traits, Allocator>& lhs,
     const basic_string <charT, traits, Allocator>& rhs)
{
  return (lhs.compare (rhs) >= 0);
}

 

// 有关字符串的输入输出将会在 io分析过程中给出

 

} // extern "C++"