c++ - Can raw pointers be used instead of iterators with STL algorithms for containers with linear storage? -
i have custom vector container internally stores item linear array. last night, trying implement custom iterators class able use them stl algorithms. have had success can see in here:
while doing so, discovered can merely pass raw pointers stl algorithm , seem work fine. here's example without iterators:
#include <cstddef> #include <iostream> #include <iterator> #include <algorithm> template<typename t> class my_array{ t* data_; std::size_t size_; public: my_array() : data_(null), size_(0) {} my_array(std::size_t size) : data_(new t[size]), size_(size) {} my_array(const my_array<t>& other){ size_ = other.size_; data_ = new t[size_]; (std::size_t = 0; i<size_; i++) data_[i] = other.data_[i]; } my_array(const t* first, const t* last){ size_ = last - first; data_ = new t[size_]; (std::size_t = 0; i<size_; i++) data_[i] = first[i]; } ~my_array(){ delete [] data_; } const my_array<t>& operator=(const my_array<t>& other){ size_ = other.size_; data_ = new t[size_]; (std::size_t = 0; i<size_; i++) data_[i] = other.data_[i]; return other; } const t& operator[](std::size_t idx) const {return data_[idx];} t& operator[](std::size_t& idx) {return data_[idx];} std::size_t size(){return size_;} t* begin(){return data_;} t* end(){return data_+size_;} }; template<typename t> void print(t t) { std::cout << t << std::endl; } int main(){ typedef float scalar_t; scalar_t list [] = {1, 3, 5, 2, 4, 3, 5, 10, 10}; my_array<scalar_t> a(list, list+sizeof(list)/sizeof(scalar_t)); // works! (scalar_t* = a.begin(), *end = a.end(); != end; ++it) std::cout << ' ' << *it; std::cout << std::endl; // works! std::for_each(a.begin(), a.end(), print<scalar_t>); std::cout << std::endl; // works! my_array<int> b(a.size()); std::copy(a.begin(), a.end(), b.begin()); // works! scalar_t* end = std::remove(a.begin(), a.end(), 5); std::for_each(a.begin(), end, print<scalar_t>); std::cout << std::endl; // works! std::random_shuffle(a.begin(), end); std::for_each(a.begin(), end, print<scalar_t>); std::cout << std::endl; // works! std::cout << "counts of 3 in array = " << std::count(a.begin(), end, 3) << std::endl << std::endl; // works! std::sort(a.begin(), end); std::for_each(a.begin(), end, print<scalar_t>); std::cout << std::endl; // works! if (!std::binary_search(a.begin(), a.end(), 5)) std::cout << "removed!" << std::endl; return 0; }
live example without iterators
my questions here following:
- does work containers have linear storage? know not work linked-lists example.
- if work in situation, why should ever go through hassle of implementing iterators anyway? know how iterators generalize code , whatnot, if simple array is ever need don't see point.
- what negative issues of i'm doing if approach work? 1 thing, can see i'm breaking data encapsulation.
one of features of iterators being based on operator-overloading, pointers random-access iterators. big design win in days of stl, made easier use algorithms existing code (as making interface more familiar programmers). it's reasonable wrap array, add typedef t* iterator; typedef const t* const_iterator
, return &array[0]
begin()
, &array[size]
end()
, , use container iterator-based algorithm. realise, work container elements contiguous in memory (such array).
you might implement 'real' iterators if:
- you have different-shaped container (such tree or list);
- you want able resize array without invalidating iterators;
- you want add debugging checks iterator use, example check if iterator used after being invalidated or after container has been deleted, or bounds-check;
- you want introduce type-safety, , make sure people can't accidentally assign arbitrary
t*
my_array::iterator
.
i'd last advantage alone worth writing trivial wrapper class for. if don't take advantage of c++'s type system making different kinds of thing have different types, might switch javascript :-)
Comments
Post a Comment