📄 l3_array_base.h
字号:
#ifndef _INCLUDED_L3_ARRAY_BASE_H#define _INCLUDED_L3_ARRAY_BASE_H// Copyright (C) Krzysztof Bosak, 1999-07-22...2001-01-10.// All rights reserved.// kbosak@box43.pl// http://www.kbosak.prv.pl#include "l3_array_common.h"/////////////////////////////////////////////////////////////////////////////template<class type>class basearray: protected common_array_algorithms<type>{ // Corresponds to std::valarray. // For objects with trivial constructors and destructors: // for which new/delete in constructors/destructors are NOT ALLOWED. // Unused objects ARE NOT DESTROYED IMMEDIATELY during resizing, often much later. // Uses non-deallocated memory for buffered allocations (after diminishing the size). // operator= and copy constructor can change size. // Assumptions on type: // - The type has garbage-initializing default constructor (ev. default one). // - The type has byte-copying copy constructor (ev. default one). // - The type has byte-copying assignment operator (ev. default one). // - The type has trivial destructor // (in particular no dynamic memory allocation by type allowed) (ev. default one). // - The type does not have any data members that are references (to allow copying). // - All base classes and all data memeber objects of type must have trivial // assignment operators. // - As a result, operator=, copy construtor and default constructor are supposed // not to throw any exceptions. // - type(0) must have null-bytes representation when using erase() // Under those assumptions is EXCEPTION NEUTRAL.protected: int _size; int _capacity; type * _data;public: basearray(); explicit basearray(int requested_size); // EXCEPTION NEUTRAL basearray(const basearray<type>& src); // EXCEPTION NEUTRAL // Implicit. basearray(const type * const arr, int requested_size); // EXCEPTION NEUTRAL basearray(int requested_size, const type & fill_value); // EXCEPTION NEUTRAL // Efficient nonstandard extension: void setsize(int requested_size); // not STL // EXCEPTION NEUTRAL basearray<type>& operator=(const basearray<type>& other); // EXCEPTION NEUTRAL inline virtual ~basearray() // NOTHROW { // Aggressive destructor _GarbageFillLoop(_data, _capacity);// Use only trivial destructors with this class! delete[] _data; } inline type & operator[](int element_index) // EXCEPTION NEUTRAL { // Returns object contained in array by reference, changes are possible INDEXING_TEST(_size); return _data[element_index]; } inline const type & operator[](int element_index) const // EXCEPTION NEUTRAL { // Returns object contained in array by reference, no changes to data INDEXING_TEST(_size); return _data[element_index]; } inline void clear() // NOTHROW { _size=0; } inline int size() const // NOTHROW { // Returns current size of array return _size; } inline int max_size() const // NOTHROW { // 2 times smaller than for std::allocator due to 'int' used instead of 'unsigned' return INT_MAX/sizeof(type); } inline bool empty() const // NOTHROW { // Is array empty? return _size==0; } inline int capacity() const // NOTHROW { // Returns current capacity of array return _capacity; } void resize(int requested_size); // EXCEPTION NEUTRAL void reserve(int reserve_size); // EXCEPTION NEUTRAL inline void swap(basearray<type>& other); // NOTHROW // STL compliant, but less recommended: /// inline type & front() // NOTHROW { assert(_size>0); return _data[0]; } inline const type & front() const // NOTHROW { assert(_size>0); return _data[0]; } inline type & back() // NOTHROW { assert(_size>0); return _data[_size-1]; } inline const type & back() const // NOTHROW { assert(_size>0); return _data[_size-1]; } /// inline void push_back(const type & object) // EXCEPTION NEUTRAL { #ifdef USE_ARRAY_EXCEPTIONS // Commit or rollback... Very costly. basearray<type> temp(((_size+1)<<1)+1); temp.setsize(_size+1); _UnrolledCopyLoop(temp._data, _data, _size); temp.back()=object; swap(temp); #else // Rather costly. const int oldsize=_size; if(oldsize+1>_capacity) { resize(((oldsize+1)<<1)+1); } _size=oldsize+1; _data[oldsize]=object; #endif } void pop_back() // NOTHROW { assert(_size>0); _size--; } /// inline type & at(int element_index) // NOTHROW { // Returns object contained in array by reference. INDEXING_TEST(_size); return _data[element_index]; } inline const type & at(int element_index) const // NOTHROW { // Returns object contained in array by reference, no changes allowed. INDEXING_TEST(_size); return _data[element_index]; } /// inline type * begin() // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data; } inline const type * begin() const // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data; } inline type * end() // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data+_size; } inline const type * end() const // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data+_size; } /// inline type * rbegin() // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data+_size-1; } inline const type * rbegin() const // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data+_size-1; } inline type * rend() // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data-1; } inline const type * rend() const // NOTHROW { assert(_size>0);// STL doesn't require to have nonempty sequence here. return _data-1; } /// inline int memory() const // not STL // NOTHROW { // Returns memory usage of array in bytes assert(_capacity>=_size); return _capacity*sizeof(type)+sizeof(*this); } inline void free() // not STL // NOTHROW { // Sets array to minimum usage of memory _GarbageFillLoop(_data, _capacity); delete[] _data; _data=NULL;// A must: delete operator must not set _data to NULL, by C++ standards, (and very rarely does it) _size=0; _capacity=0; } void trim(); // not STL // EXCEPTION NEUTRAL void reverse(); // not STL // NOTHROW inline void erase() // not STL // NOTHROW { if(_size>0) { memset(_data, 0, sizeof(type)*_size); } } inline void fill(const type & fill_value) // not STL // NOTHROW { // Fills the whole array with given value _UnrolledFillLoop(_data, fill_value, _size); }};template<class type>basearray<type>::basearray() // NOTHROW : _size(0), _capacity(0), _data(NULL){ // Quick default constructor}template<class type>basearray<type>::basearray(int requested_size) // EXCEPTION NEUTRAL{ // Constructor assert(requested_size>=0); assert(requested_size<=max_size()); if(requested_size==0) { _size=0; _capacity=0; _data=NULL; return; } _size=requested_size; _capacity=requested_size; _data=new type[requested_size]; MEMORY_ALLOCATION_TEST(_data, requested_size); _GarbageFillLoop(_data, _size);// Trivial constructors with this class only!}template<class type>basearray<type>::basearray(const basearray<type>& src) // EXCEPTION NEUTRAL{ // Copy constructor assert(&src!=this); if(src._size==0) { _size=0; _capacity=0; _data=NULL; return; } _size=src._size; _capacity=src._size; _data=new type[src._size]; MEMORY_ALLOCATION_TEST(_data, src._size); memcpy(_data, src._data, _size*sizeof(type));// Trivial assignment operators with this class only!}template<class type>basearray<type>::basearray(const type * const arr, int requested_size) // EXCEPTION NEUTRAL{ // Constructor from const C array assert(requested_size>=0); assert(requested_size<=max_size()); if(requested_size==0) { _size=0; _capacity=0; _data=NULL; return; } assert(arr!=NULL); _size=requested_size; _capacity=requested_size; _data=new type[requested_size]; MEMORY_ALLOCATION_TEST(_data, requested_size); memcpy(_data, arr, _size*sizeof(type));}template<class type>basearray<type>::basearray(int requested_size, const type & fill_value) // EXCEPTION NEUTRAL{ // Filling constructor assert(requested_size>=0); assert(requested_size<=max_size()); if(requested_size==0) { _size=0; _capacity=0; _data=NULL; return; } _size=requested_size; _capacity=requested_size; _data=new type[requested_size]; MEMORY_ALLOCATION_TEST(_data, requested_size); _UnrolledFillLoop(_data, fill_value, _size);}// Efficient nonstandard extension:template<class type>void basearray<type>::setsize(int requested_size) // not STL // EXCEPTION NEUTRAL{ // Resizes, but does not prevents content of array, may preserwe some old, // unused memory for future assert(requested_size>=0); assert(requested_size<=max_size()); assert(_size<=_capacity); _GarbageFillLoop(_data, _capacity); if(requested_size>_capacity) { assert(requested_size>0); _GarbageFillLoop(_data, _capacity); type * const temp=new type[requested_size]; MEMORY_ALLOCATION_TEST(temp, requested_size); _capacity=requested_size; delete[] _data; _data=temp; _GarbageFillLoop(_data, requested_size); } _size=requested_size;}template<class type>basearray<type>& basearray<type>::operator=(const basearray<type>& other) // EXCEPTION NEUTRAL{ // Assignment operator, faster than with autoarray (and still ex. neutral) //assert(this!=&other);// This line can be safely removed. if(&other!=this) { setsize(other._size); if(_size>0) { assert(_data!=NULL); memcpy(_data, other._data, _size*sizeof(type)); } } return *this;}template<class type>void basearray<type>::resize(int requested_size) // EXCEPTION NEUTRAL{ // Resizes and prevents content of array assert(requested_size>=0); assert(requested_size<=max_size()); assert(_size<=_capacity); if(requested_size>_capacity) { //cout<<"resize: "<<_size<<" to "<<requested_size<<endl; assert(requested_size>0); _capacity=requested_size; type * const temp=new type[requested_size]; MEMORY_ALLOCATION_TEST(temp, requested_size); _GarbageFillLoop(temp, _capacity); if(_size>0) { assert(_data!=NULL); memcpy(temp, _data, _size*sizeof(type)); } _GarbageFillLoop(_data, _size); delete[] _data; _data=temp; } _size=requested_size;}template<class type>void basearray<type>::reserve(int reserve_size) // EXCEPTION NEUTRAL{ // Sets _capacity for max(reserve_size, _capacity), // will ensure quick resizing in future for up to reserve_size array size assert(reserve_size>=0); assert(reserve_size<=max_size()); if(reserve_size<=_capacity) { return; } const int oldsize=_size; resize(reserve_size); _size=oldsize;}template<class type>void basearray<type>::swap(basearray<type>& other) // NOTHROW{ // Swaps whole content of 2 arrays (useful for updating new vector of values), // array size can differ. int itemp=other._size; other._size=_size; _size=itemp; itemp=other._capacity; other._capacity=_capacity; _capacity=itemp; type * const ptemp=other._data; other._data=_data; _data=ptemp;}template<class type>void basearray<type>::trim() // not STL // EXCEPTION NEUTRAL{ // Sets _capacity for _size, type * const buffer=new type[_size]; memcpy(buffer, _data, _size*sizeof(type)); delete[] _data; _data=buffer; _capacity=_size;}template<class type>void basearray<type>::reverse() // not STL // NOTHROW{ const int sb2=_size>>1; for(int i1=0, i2=_size-1; i1<sb2; i1++, i2--) { const type temp=_data[i1]; _data[i1]=_data[i2]; _data[i2]=temp; }}/////////////////////////////////////////////////////////////////////////////#endif //_INCLUDED_L3_ARRAY_BASE_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -