008: constructor with size, and destructor

いよいよ領域確保を伴う処理の実装に入っていきます。
初めに作成するのは、サイズ指定のコンストラクタです。さらに、領域確保に対応して領域を解放するデストラクタも合わせて実装します。
領域確保のために、2つの補助関数 check_length() と mymalloc() もそれぞれ定義します。
template <typename T>
class myvector
{
...

    /**
     * @brief      Constructor with size. Constructs the container with count
     *             default-inserted instances of T.
     * @param[in]  count: The size of the container.
     * @throw      std::length_error: If count is greater than max_size().
     * @throw      std::bad_alloc: If malloc() fails to allocate storage.
     */
    explicit myvector(size_type count) :
        heap_(count ? mymalloc(length_check(count)) : nullptr),
        size_(count),
        capacity_(count)
    {
        for (size_type i = 0; i < size_; i++) {
            new(&heap_[i]) value_type();
        }
    }

    /**
     * @brief      Destructor. Destructs the vector.
     */
    ~myvector(void)
    {
        for (size_type i = 0; i < size_; i++) {
            heap_[i].~value_type();
        }
        free(heap_);
        heap_ = nullptr;
        size_ = 0;
        capacity_ = 0;
    }
...

private:
    /**
     * @brief      Checks new container size.
     * @param[in]  count: Number of elements.
     * @return     Same as count.
     * @throw      std::length_error: If count is greater than the maximum size.
     */
    size_type length_check(size_type count) const
    {
        if (count > MAX_SIZE) {
            throw std::length_error("myvecotr::length_check()");
        }

        return count;
    }

    /**
     * @brief      Calls malloc with (sizeof(value_type) * count).
     * @param[in]  count: Number of elements. Should be count > 0.
     * @return     A pointer to the memory block allocated by malloc().
     * @throw      std::bad_alloc: If malloc() fails to allocate storage.
     */
    pointer mymalloc(size_type count)
    {
        void* p = malloc(sizeof(value_type) * count);
        if (p == nullptr) {
            throw std::bad_alloc();
        }

        return static_cast<pointer>(p);
    }

...
};
myvectorクラスでは、new と delete は使用しません。new ではなく malloc() と placement new を、delete ではなく デストラクタと free() をそれぞれ使います。このようにする理由は、placement new を使わないと、複数の要素のコンストラクタに対して、別々の引数を渡すことができないからです。

length_check() は std::length_error を投げるかどうかを決定する関数です。この関数は、mymalloc() の引数として使われることを想定しています。
mymalloc() は malloc() のラッパー関数です。malloc() の結果が失敗だった場合(戻り値が nullptr だった場合)、std::bad_alloc() を投げます。

コンストラクタでは、領域確保後に placement new を使って各要素を初期化します。
デストラクタでは、各要素のデストラクタを呼んだ後、free() で領域を開放します。


全ソースコード: https://github.com/suomesta/myvector/tree/master/008

0 件のコメント:

コメントを投稿