3

最近、既存のクラスの多くをスマートポインターの使用に移行し始めました。スマートポインターを使用することでメリットが得られると思われるコードを移植する方法について、いくつか質問があります(もちろん間違っているかもしれません)。ヘッダーファイルを介して、以下に示すUtlMemBufferバッファーマネージャークラスがあります 。

基本的に、このクラスは、void */lengthのペアで構成されるバッファーのベクトルを所有します。バッファ管理は、ヘルパーメソッド(UtlMemBuffer :: append-その実装も以下に示されています)を介して実装されます。

このクラスで新しいC++11スマートポインターを使用して、所有権を適切に定義し、再割り当てを最小限に抑えたいと思います。このクラスを使用するために、クライアントコードは通常、独自のrawポインターバッファー/長さをコンストラクターに渡すか、appendを呼び出すことができます。最終的に、UtlMemBufferのデストラクタが呼び出されると、UtlMemBufferはそれ自体のコピーを解放し、呼び出し元がそのコピーを担当している間、メモリリークが発生しないようにします。生のポインターを渡す代わりに、std :: shared_ptrを使用すると、このタイプの二重バッファー所有権が不要になると思いますつまり、呼び出し元はstd :: shared_ptrを更新し、それをUtlMembufferに渡す責任があります。

私が見ている最大の課題は、生のポインタを介してフラット化されたメモリを返す必要があるreadメソッド(インターフェイスはファイルの動作方法に似ています)をサポートすることです。おそらく、より良い設計アプローチは、shared_ptrsの内部コレクションをフラット化して作成したstd::unique_ptrを返すことです。最善のアプローチが何であるかはよくわかりませんが、そのアプローチを採用するためにクラスを使用する現在のコードをかなり変更する必要があります。

呼び出し元がすべて、exのstd::shared_ptrポインタを渡す必要があります。この変換を行うための最良のアプローチは何でしょうか。

私はこのスマートポインタビジネスにかなり慣れていないので、アドバイスをいただければ幸いです。ありがとう

/**
 * Smart Buffer class
 */
class UtlMemBuffer
{
public:
    // default constructor
    UtlMemBuffer(
        const UtlPath& rBufferPath = UtlPath::ssNull,
        const void* pBytes = NULL,
        const size_t& rBufLength = 0);

    // copy constructor
    UtlMemBuffer(const UtlMemBuffer& rhs);

    // move constructor
    UtlMemBuffer(UtlMemBuffer&& rhs);

    inline void swap(UtlMemBuffer& rhs) throw() {
        // enable ADL (not necessary in our case, but good practice)
        using std::swap;
        // no need to swap base members - as we are topmost class
        swap(mBufferPath, rhs.mBufferPath);
        swap(mBufferLength, rhs.mBufferLength);
        swap(mBufferBlocks, rhs.mBufferBlocks);
    }

    // unified assignment operator
    UtlMemBuffer& operator=(UtlMemBuffer rhs);

    // destructor - pure virtual
    virtual ~UtlMemBuffer();

    // add buffer to this one
    virtual OsStatus append(
        const void* pBytes,
        const size_t& rBufLength,
        size_t& rBufLengthWritten);

    // comparator
    bool operator==(const UtlMemBuffer& rhs) const;

    // comparator
    bool operator<(const UtlMemBuffer& rhs) const;

    // determine the size of the buffer
    size_t size() const;

    /**
     * comparable interface
     *
     * @returns 0 if equal, negative val if less than &
     *          negative value if greater.
     */
    virtual int compareTo(const UtlMemBuffer& rhs) const;

    /** copy the bytes into the designated buffer */
    OsStatus read (void* pReturnBuffer,
        const size_t& rMemBufferOffset,
        const size_t& rReturnBufferLength,
        size_t& rBytesRead) const;

    // free existing linked list of blocks
    void clear();

    // path property
    void setBufferPath(const UtlPath& rBufferPath);

    UtlPath getBufferPath() const;

private:
    typedef std::vector< std::pair<void*, size_t> > MemBufInfo;

    // the name of the buffer (sort of file name)
    UtlPath mBufferPath;

    // this is updated whenever we append data
    size_t mBufferLength;

    // here we have a collection of received appends (effectively blocks)
    MemBufInfo mBufferBlocks;
};

これは、バッファブロックのベクトルへのアクセスを管理するヘルパーメソッドです。ご覧のとおり、rawポインターを再割り当てし、mBufferBlocksメンバーに格納します。

OsStatus
UtlMemBuffer::append(const void* pBytes,
    const size_t& rBufLength,
    size_t& rBytesWritten)
{
    rBytesWritten = 0;
    if (pBytes != NULL) {
        void* block = new char [rBufLength];
        memcpy(block, pBytes, rBufLength);
        mBufferBlocks.push_back(std::make_pair(block, rBufLength));
        rBytesWritten = rBufLength;
        mBufferLength += rBufLength;
    }
    return OS_SUCCESS;
}
4

1 に答える 1

1

作成者が通常のように単にchar*を使用してメモリバイトを表す場合は、void */lenのペアの代わりにベクトルを単純に格納することができます。

それは私がおそらくここで行うことです。このメモリ空間内のオブジェクトを実際に破棄する必要がないと仮定すると、char *にキャストして、ベクトルに貼り付けるだけです。

于 2012-05-02T17:16:54.677 に答える