std::shared_ptr и memory allocator
От: lnkuser  
Дата: 25.03.16 16:28
Оценка:
Добрый день!


Задача: создавать очень быстро std::shared_ptr для объекта небольшого класса.
Подскажите пожалуйста как правильно работать с std::shared_ptr && allocator/deallocator чтобы избежать двойного выделения памяти для самого объекта и control block.


#include <iostream>
#include <memory>
#include "memory_allocator.hpp"



class Frame
{
    public:
        Frame() {std::cout << __func__ << std::endl;};
        ~Frame() {std::cout << __func__ << std::endl;};
};

//----------------------------------------------------------------------

int main()
{
    MemoryAllocator<Frame> allocator;


    auto deleter = [&](Frame* frame) {
        std::cout << "[deleter called] " << frame << std::endl;
        allocator.deallocate(frame);
    };

    auto ptr = allocator.allocate();
    std::shared_ptr<Frame> frame(ptr, deleter, allocator);


    return 0;
}



Простой аллокатор, запиленный по примерам в интернете:
template<typename T>
class MemoryAllocator
{
    public:
        using value_type = T;
        using pointer = T*;
        using const_pointer = const T*;
        using reference = T&;
        using const_reference = const T&;
        using size_type = std::size_t;
        using difference_type = std::ptrdiff_t;

        MemoryAllocator() noexcept {std::cout << "ctor " << this << std::endl;};
        MemoryAllocator(const MemoryAllocator&) noexcept {std::cout << "copy ctor " << this << std::endl;};
        template<typename U>
        MemoryAllocator(const MemoryAllocator<U>&) noexcept {std::cout << "template copy ctor " << this << std::endl;};
        ~MemoryAllocator() noexcept {std::cout << "dtor " << this << std::endl;};

        pointer allocate() {
            auto ptr = static_cast<pointer>(::operator new(sizeof(T)));

            std::cout << this << " " <<__func__ << " " << ptr << std::endl;

            return ptr;
        }

//----------------------------------------------------------------------

        pointer allocate(size_type n, const void* = 0) {
            auto ptr = static_cast<pointer>(::operator new(n * sizeof(T)));

            std::cout << this << " " << __func__ << " " << ptr << " " << n << std::endl;

            return ptr;
        }

//----------------------------------------------------------------------

        void deallocate(pointer ptr) {
            std::cout << this << " " << __func__ << " " << ptr << std::endl;
        }

//----------------------------------------------------------------------

        void deallocate(pointer ptr, size_type) {
            std::cout << this << " " << __func__ << " " << ptr << std::endl;
        }
};


Получаем такой вывод.


ctor 0x7fff54e392d8
0x7fff54e392d8 allocate 0x1074010
copy ctor 0x7fff54e39298
copy ctor 0x7fff54e39238
copy ctor 0x7fff54e391d8
template copy ctor 0x7fff54e39170
0x7fff54e39170 allocate 0x1074030 1
copy ctor 0x1074040
dtor 0x7fff54e39170
dtor 0x7fff54e391d8
dtor 0x7fff54e39238
dtor 0x7fff54e39298
[deleter called] 0x1074010
0x7fff54e392d8 deallocate 0x1074010
template copy ctor 0x7fff54e391c0
dtor 0x1074040
0x7fff54e391c0 deallocate 0x1074030
dtor 0x7fff54e391c0
dtor 0x7fff54e392d8



Как видно, вроде все хорошо, сам объект и control блок выделяются через аллокатор и удаляются так же.
Но!
Почему здесь там много всяких copy ctor ?
Как можно использовать только один аллокатор и почему он так много раз копируется ?


P.S. извините за скудные познания в memory allocation, первый раз сталкиваюсь. Спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.