在這里,我們發現了一個垃圾收集機制真正能夠發揮無可比擬的地方。借助于垃圾收集,前面討論的RVL(返回值生命期)問題迎刃而解。由于垃圾收集的工作機制是釋放那些不再被活躍代碼所引用的內存,所以毫無疑問,當一個指向堆分配的內存塊的指針在仍然被需要的時候是被會失效的。我們所要做的就是返回一個新分配的堆內存塊而已。
template<typename T,
typename A = typename allocator_selector<T>::allocator_type,
typename P = do_construction<T>,
bool R = true>
class fixed_array_2d : protected A, public stl_collection_tag
{
public:
typedef fixed_array_2d< T, A, P, R > class_type;
typedef fixed_array_1d< T, A, P, false > dimension_element_type;
typedef A allocator_type;
typedef T value_type;
typedef value_type & reference;
typedef value_type const & const_reference;
typedef value_type * pointer;
typedef value_type const * const_pointer;
typedef size_t size_type;
typedef size_t index_type;
typedef ss_ptrdiff_t difference_type;
typedef bool bool_type;
typedef pointer_iterator< value_type, pointer, reference >::type iterator;
typedef pointer_iterator< value_type const , const_pointer, const_reference >::type const_iterator;
// 構造函數
private:
// 切片構造
fixed_array_2d(T *data, index_type d0, index_type d1);
public:
// 標準構造
fixed_array_2d (index_type d0, index_type d1);
fixed_array_2d (index_type d0, index_type d1, allocator_type const &ator);
fixed_array_2d (index_type d0, index_type d1, value_type const &t);
fixed_array_2d (index_type d0, index_type d1, value_type const &t, allocator_type const &ator);
fixed_array_2d (class_type const &rhs);
~fixed_array_2d();
allocator_type get_allocator () const;
void swap (class_type &rhs); throw ();
// 訪問
public:
reference at (index_type i0, index_type i1);
const_reference at (index_type i0, index_type i1) const;
reference at_unchecked (index_type i0, index_type i1);
const_reference at_unchecked (index_type i0, index_type i1) const;
reference operator(); (index_type i0, index_type i1);
const_reference operator(); (index_type i0, index_type i1) const;
dimension_element_type at (index_type i0);
const dimension_element_type at (index_type i0) const;
dimension_element_type at_unchecked (index_type i0);
const dimension_element_type at_unchecked (index_type i0) const;
dimension_element_type operator[] (index_type i0);
const dimension_element_type operator[] (index_type i0) const;
reference front ();
reference back ();
const_reference front () const;
const_reference back () const;
pointer data ();
const_pointer data () const;
// 迭代
public:
iterator begin ();
iterator end ();
const_iterator begin () const;
const_iterator end () const;
// 狀態
public:
index_type dimension0 () const;
index_type dimension1 () const;
index_type size () const;
bool_type empty () const;
static size_type max_size ();
// 實現
private:
pointer allocate_(size_type n);
void deallocate_(pointer p, size_type n);
pointer data_();
index_type calc_index_(index_type i0, index_type i1) const;
void range_check_(index_type i0, index_type i1) const;
void range_check_(index_type i0) const;
allocator_type& get_allocator_();
// 成員
private:
T* m_data;
index_type m_d0;
index_type m_d1;
size_type m_size;
friend class fixed_array_3d<T, A, P, true>;
friend class fixed_array_3d<T, A, P, false>;
// 聲明但不實現
private:
class_type const& operator =(class_type const& rhs);
};
另外,C/C++對固定大小的數組支持是無容置疑的,但為了獲得通過bein()/end()來獲得對整個數組進行迭代的能力,我們也設計了一組模板類來模擬靜態多維數組。static_array自身并不進行任何形式的內存分配:如果它的身份是作為一個切片代理,它只會保存一個指向數組切片的指針;倘若它本身作為一個完整的數組,則會包含一個完整的N維內建數組。
泛化的仿函數 —— 類型隧道(Type Tunneling):是一種通過訪問墊片使兩個邏輯相關但物理不相關的類型能夠互操作的機制,墊片允許一個外部類型通過一個接口以一種可識別且兼容的形式呈現于內部類型的面前。
template<typename C,
typename A = C const *>
class is_large : public std::unary_function<A, bool>
{
public:
template<typename S>
bool operator ()(S const& file) const
{
return is_large_(c_str_ptr(file)); // c_str_ptr墊片
}
private:
static bool is_large_(C const* file)
{
...
}
};
glob_sequence gs("/usr/include/", "impcpp*");
std::count_if(gs.begin(), gs.end(), is_large<char>());
glob_sequenc_w gsw(L"/usr/include/", L"impcpp*");
std::count_if(gsw.begin(), gsw.end(), is_large<wchar_t>());
readir_sequence rs("/usr/include/");
std::count_if(rs.begin(), rs.end(), is_large<char>());