Hello from lk's World

12 May 2014 » 从 std::ratio 看编译期运算

<ratio> 提供了 编译期 分数运算功能(还记得当年 OOP 课上要写一个分数类,不过是运行时的)。编译期呢,也就是说分母(numerator)和分子(denominator)都是在编译期时就是确定的,并且在编译期完成所需的各种运算。

先抄一个 ratio 使用的例子:

#include <iostream>
#include <ratio>

int main ()
{
  typedef std::ratio<1,3> one_third;
  typedef std::ratio<2,4> two_fourths;
  typedef std::ratio_add<one_third,two_fourths> sum;

  std::cout << "sum= " << sum::num << "/" << sum::den;
  std::cout << " (which is: " << ( double(sum::num) / sum::den ) << ")" << std::endl;

  return 0;
}

10 May 2014 » containers,unordered 系列与 hashtable

总算把中期报告搞定了,可以继续搞起。 ​ C++11 中, 多了 4 个 unordered 容器,分别是 unordered_set, unordered_multiset, unordered_map, unordered_multimap。当然,也略有耳闻里面是用 hash table 来做的,今天一探究竟。

先来看看 unordered_map, include/bits/unordered_map.h

  template<class _Key, class _Tp,
           class _Hash = hash<_Key>,
           class _Pred = std::equal_to<_Key>,
           class _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
    class unordered_map
    {
      typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
      _Hashtable _M_h;

发现里面有一个 _Hashtable,相似的在 multimap 中。

  template<class _Key, class _Tp,
           class _Hash = hash<_Key>,
           class _Pred = std::equal_to<_Key>,
           class _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
    class unordered_multimap
    {
      typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
      _Hashtable _M_h;

05 May 2014 » containers,inside std::deque

继续 container ~ 来到 inlcude/bits/stl_deque.h 假设我们对 deque 的内存布局一无所知,然后来看代码看看能不能看出蛛丝马迹。

  /**
   * @brief This function controls the size of memory nodes.
   * @param __size The size of an element.
   * @return The number (not byte size) of elements per node.
   *
   * This function started off as a compiler kludge from SGI, but
   * seems to be a useful wrapper around a repeated constant
   * expression. The @b 512 is tunable (and no other code needs to
   * change), but no investigation has been done since inheriting the
   * SGI code. Touch _GLIBCXX_DEQUE_BUF_SIZE only if you know what
   * you are doing, however: changing it breaks the binary
   * compatibility!!
  */
#ifndef _GLIBCXX_DEQUE_BUF_SIZE
#define _GLIBCXX_DEQUE_BUF_SIZE 512
#endif
  inline size_t
  __deque_buf_size(size_t __size)
  { return (__size < _GLIBCXX_DEQUE_BUF_SIZE
            ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); }

04 May 2014 » std::string 和引用计数

std::string 又是 STL 中最最最最最最最常用的没有之一的设施。正因为简单,不大被关注。 初用 C++ 的人一定不知道他是从 basic_string 特化出来的,对 C++ 有一定了解的人可能也不知道 string 里面是带引用计数的。现在就来详细剖析一下 string 或者说 basic_string 吧

include/std/string 里面是一堆的 include,就不贴出来浪费篇幅了,有关的是 stringfwd.h,basic_string.h, basic_string.tcc 三个文件。

stringfwd.h

  template<class _CharT>
    struct char_traits;
  template<typename _CharT, typename _Traits = char_traits<_CharT>,
           typename _Alloc = allocator<_CharT> >
    class basic_string;
  template<> struct char_traits<char>;
  /// A string of @c char
  typedef basic_string<char> string;
#ifdef _GLIBCXX_USE_WCHAR_T
  template<> struct char_traits<wchar_t>;
  /// A string of @c wchar_t
  typedef basic_string<wchar_t> wstring;
#endif
#if ((__cplusplus >= 201103L) \
     && defined(_GLIBCXX_USE_C99_STDINT_TR1))
  template<> struct char_traits<char16_t>;
  template<> struct char_traits<char32_t>;
  /// A string of @c char16_t
  typedef basic_string<char16_t> u16string;
  /// A string of @c char32_t
  typedef basic_string<char32_t> u32string;

03 May 2014 » containers,std::vector

vector 是最最最最最喜闻乐见没有之一的容器了。然后,由于众所周知的原因,略过 vector<bool>

gcc 家的 stl 除了提供了基本的 container,还给了配套的 debugprofile 设施。

另外一些算法还提供了 parallel mode。

不过话说回来,感觉 debug mode 和 profile mode 都很积累。debug 报不出行号,内存泄露似乎还是 valgrind 和 tcmalloc 跑起来比较舒服,越界访问直接 gdb 就能定位到行。profile 会给出建议或者性能表现的特性,还是不如直接上 perf 或者 vtune。。。。不过有空还是可以去研究一下内部的原理。

include/bits/vector

  template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class vector : protected _Vector_base<_Tp, _Alloc>