私は、アイテムを線形配列で内部的に格納するカスタムベクターコンテナを持っています。昨夜、クラスのカスタムイテレータをSTLアルゴリズムで使用できるように実装しようとしていました。そうリニアストレージを持つコンテナのSTLアルゴリズムでイテレータの代わりにローポインタを使用できますか?
Live example with custom iterators
ながら、私は単にSTLアルゴリズムに生のポインタを渡すことができます発見し、彼らはうまく動作するようです:私はあなたがここで見ることができるいくつかの成功を収めています。ここでの例では、任意のイテレータなしだ:
#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_];
for (std::size_t i = 0; i<size_; i++)
data_[i] = other.data_[i];
}
my_array(const T* first, const T* last){
size_ = last - first;
data_ = new T[size_];
for (std::size_t i = 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_];
for (std::size_t i = 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!
for (scalar_t* it = a.begin(), *end = a.end();
it != 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
ここでの私の質問は以下の通りです:
- これは常に線形ストレージを持っているコンテナのために働くのか?私はこれが例えばリンクリストのためにはうまくいかないことを知っています。
- もしこのような状況で動作するのであれば、なぜイテレータを実装するのが面倒なのですか?私はイテレータが私のコードとその他のものを一般化する方法を知っていますが、このシンプルな配列がなら、私はポイントを見ません。
- このアプローチが常に有効な場合、私がやっていることの否定的な問題は何ですか?一つ目は、私はデータのカプセル化を壊しているのが分かります。
'&array [size]'には注意が必要です。http://stackoverflow.com/q/26420348/893406 –
@ v.oddouいいえ、 '&array [size]'は常に有効です。 (あなたがそれを逆参照しない限り)、あなたのリンクの答えが説明するように。あなたは正しいコードであるかどうかを推論する必要があります:あなたは神秘主義を使うことはできません。 –
ページIのリンク全体の議論によれば、このアドレスがマップされていなければ、クラッシュを引き起こすためにポインタレジスタにアドレスをロードすれば十分です。いくつかのアーキテクチャでは。したがって、それを逆参照しないことだけではありません。ここにはカーゴカルトはありません。 –