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

При поиске методов перегрузки оператора 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() мы получаем тот же результат.

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

2

Решение

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

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

3

Другие решения

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

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

2

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

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% лучше, когда они вам нужны, но лучше их избегать, когда вы этого не делаете.

2
По вопросам рекламы [email protected]