Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

Умный указатель и массив

#cpp #шаблоны_с++


Задача поставлена следующим образом: создать класс умный указатель, с которым можно
будет реализовать следующее:

int main()
{
    SmartPointer  p1 = new int(2);
    p1->Method1();
    p1[2] = int(); // должна быть ошибка на этапе компиляции
    SmartPointer  p2 = new int[3];
    p2->Method1(); //должна быть ошибка на этапе компиляции
    p2[2] = int();
    return 0;
}


если создаем объект Object = new Object(3); - тогда мы можем обратиться с помощью
стрелки ко всем методам которыми обладает объект Object
если мы создали массив объект Object = new Object[3] - тогда мы не можем обратиться
с помощью стрелки к массиву.

Код ниже:

template 
class SmartPointer
{
private:
    DefaultDeleter m_deleter;

    Counter *m_count = nullptr;
    T *m_ptr = nullptr;

    typedef std::remove_all_extents_t ptr;

public:
    SmartPointer(T* const ptr) :
        m_count(new Counter),
        m_ptr(ptr)
    {
        m_count->incrementCount();
    }

    SmartPointer(const SmartPointer &source)
        m_count(source.m_count),
        m_ptr(source.m_ptr)
    {
        m_count->incrementCount();
    }

    SmartPointer& operator=(const SmartPointer &right)
    {
        m_count->decrementCount();
        return SmartPointer(right).Swap(*this);
    }
    T& operator*()
    {
        return *m_ptr;
    }
    T* operator->()
    {
        return m_ptr;
    }
    T& operator[](unsigned int index)
    {
        return m_ptr[index];
    }


    SmartPointer& Swap(SmartPointer& other)
    {
        std::swap(m_ptr, other.m_ptr);
        return *this;
    }
    ~SmartPointer()
    {
        {
            m_count->decrementCount();
            if (m_count->getCount() == 0)
            {
                m_deleter.Delete(m_ptr);
                delete m_count;
            }
        }
    }
};

template 
class DefaultDeleter 
{
public:
    void Delete(T* const ptr)
    {
        delete ptr;
    }
};

template 
class DefaultDeleter 
{
public:
    void Delete(T* const ptr)
    {
        delete[] ptr;
    }
};

class Counter
{
private:
    unsigned int m_uses=0;
    public:
    void incrementCount()
    {
    ++m_uses;
    }
    void decrementCount()
    {
    --m_uses;
    }
    unsigned int getCount()
    {
    return m_uses;
    }
};


Не совсем понятно как сделать так что бы компилятор понимал где (), а где [] 
где один элемент, а где массив элементов + как исправить ошибку  в этой строке кода:

SmartPointer  p2 = new int[3]; 

    


Ответы

Ответ 1



Вам нужно просто сделать два разных класса: один для массива, другой - для скаляра. Так же это сделано для std::unique_ptr. Пример: template struct smartPtr { T* operator->() { return ptr; } T* ptr; }; template struct smartPtr { T& operator[](int i) { return ptr[i]; } T* ptr; }; struct A { void foo() {} }; int main() { smartPtr ip; ip->foo(); ip[0]; // error smartPtr ia; ia->foo(); // error ia[0].foo(); }

Комментариев нет:

Отправить комментарий