Подписка на массив: возвращение ссылки на метод класса прокси

При поиске методов перегрузки оператора Subscript('[]') для шаблонного класса я натолкнулся на два разных метода.

Первая Техника:

Перегрузка operator [] возврат указателя на контейнер напрямую, что позволит как считывать значение, так и присваивать значение. Пример реализации этого метода:

template <class T>
class X
{
    int _size;
    T *container;
public:
    X(int sz)
    {
        _size=sz;
        container=new T[sz]();
    }
    ~X()
    {

    }

    T& operator [](int indx)
    {
        return container[indx];
    }

};

С main() как:

X<int> sample(100);
cout<<sample[9]<<endl;
sample[9]=9;
cout<<sample[9]<<endl;

Выход:

0
9

Вторая техника:

Второй метод включает объявление прокси-класса и перегрузку operator = через этот класс. Пример реализации этого метода:

template <class T>
class X
{
    int _size;
    T *container;
public:
    X(int sz)
    {
        _size=sz;
        container=new T[sz]();
    }
    ~X()
    {

    }

    class Proxy
    {
        int indx;
        X<T> &parent;
    public:
        Proxy(X<T> &p, int x) : parent(p),indx(x)
        {

        }
        void operator =(T assgn)
        {
            parent.container[indx]=assgn;
        }
        operator T const &()
        {
            return parent.container[indx];
        }
        friend class X<T>;//unnecessary line, I know!
    };
    Proxy operator[](int indx)
    {
        return Proxy(*this,indx);
    }

};

С таким же main() мы получаем тот же результат.

Мне лично нравится второй способ. Но я действительно хочу сравнить эти два метода. Каковы основные функциональные различия этих двух методов. Какие преимущества имеет каждый из этих методов?

3 ответа

Решение

Описанную вами технику на основе прокси-сервера можно использовать, если вы хотите представить последовательность элементов, которые не сохраняются как таковые (требующие преобразования из и в хранилище) или к которым просто нельзя получить доступ посредством ссылки. Примером является std::vector : он упаковывает по восемь бул в каждом байте (по одному в каждом бите) в хранилище. Храня их таким образом, невозможно вернуть ссылку на один такой bool, поэтому оператор индекса вместо этого возвращает "прокси-объект" для поддержки чтения и записи содержащихся в них bool.

Если вы можете вернуть прямую ссылку на хранимые объекты, нет никакого реального преимущества в том, чтобы обернуть ее в прокси, если вы не хотите ограничить присваивание (например, разрешите только положительные значения в контейнере).

Обычно прокси используется, когда вы хотите вернуть что-то, что не соответствует внутреннему хранилищу данных. Классическим примером является 2D матрица, элементы которой хранятся в одном массиве. Если вы предоставляете оператор для возврата строк или столбцов, вам нужны прокси. Другим примером является печально известный std::vector<bool>где данные не нужно хранить как блок bool, но доступ должен вернуться bool пользователю.

Прокси могут быть использованы для возврата различных "представлений" сегментов внутреннего представления данных. В вашем примере, кажется, нет причин использовать их.

Получение прокси-объектов, подходящих для большинства клиентов, значительно сложнее... например, что если кто-то скажет:

tcp_peer.send_from_iterator_range(&sample[2], &sample[7+1]);

Если sample::operator[] возвращает временный прокси, и этот прокси не заменяет тщательно operator&Затем код запрашивает адреса самих прокси.

Некоторое использование клиента просто не может поддерживаться без потери способности Прокси перехватывать чтения и / или записи данных, например, в...

Container::element_type& ref = container[n];
ref = 20;

... код клиента предполагает наличие контейнера operator[] даст ссылку на фактический элемент. Любой прокси возвращается operator[] должен либо предоставить operator element_type&() - передать такую ​​ссылку и выйти из игры - или отказаться (например, только вернуть const ссылка, возвращает временное значение, к которому не относитсяconst ссылка не может быть связана) и принудительно вносит изменения в код клиента.

Итак, прокси на 95% лучше, когда они вам нужны, но лучше их избегать, когда вы этого не делаете.

Другие вопросы по тегам