20

アイテムを線形配列に内部的に格納するカスタム ベクター コンテナーがあります。昨夜、クラスが STL アルゴリズムで使用できるようにカスタム イテレータを実装しようとしていました。私はあなたがここで見ることができるいくつかの成功を収めました:

カスタム イテレータを使用した実際の例

そうしているうちに、生のポインターを 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;
}

イテレータなしの実際の例

ここでの私の質問は次のとおりです。

  1. これは常に線形ストレージを持つコンテナーで機能しますか? たとえば、これはリンクされたリストでは機能しないことを知っています。
  2. このような状況で機能する場合、とにかくイテレータを実装するという面倒な作業を行う必要があるのはなぜですか? イテレータがコードを一般化する方法などは知っていますが、この単純な配列だけ必要な場合は、要点がわかりません。
  3. このアプローチが常に機能する場合、私がやっていることのマイナスの問題は何ですか? 1 つには、データのカプセル化を破っていることがわかります。
4

4 に答える 4