operator[]
От: Аноним  
Дата: 16.12.04 16:57
Оценка:
есть код:

template<typename T>
class Arr
{
   T* m_pData;
   int m_nRows;

public:
   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }
   T* operator[] (size_t n) { return m_pData + n*m_nRows; }
};

//использование
Arr<int> arr(2, 2);
arr[2][1] = 3; //как выполняется опреатор [] в данной строке, какая последовательность???
Re: operator[]
От: Shady Россия  
Дата: 16.12.04 17:05
Оценка:
Здравствуйте, <Аноним>, Вы писали:

Ну это наверное акедемический пример? Там утечка памяти...
Происходит так:
  1. Вызывается operator[]. Он возвращает указатель.
  2. Возвращенный указатель увеличивается на 1 (адресная орифметика).
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re: operator[]
От: Glоbus Украина  
Дата: 16.12.04 17:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>есть код:


А>
А>Arr<int> arr(2, 2);
А>arr[2][1] = 3; //как выполняется опреатор [] в данной строке, какая последовательность???

А>


Выполняется аналогично следующему коду

int* ptr = arr[2];
ptr[1] = 3
Удачи тебе, браток!
Re[2]: operator[]
От: Shady Россия  
Дата: 16.12.04 17:10
Оценка:
S>Возвращенный указатель увеличивается на 1 (адресная орифметика).
Тьфу ты, чтобы не вводить в заблуждение, к адресу казателя прибавляется один раз размер в байтах типа указателя.
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[2]: operator[]
От: CyberZX  
Дата: 16.12.04 17:11
Оценка:
Здравствуйте, Shady, Вы писали:

S>Здравствуйте, <Аноним>, Вы писали:


S>Ну это наверное акедемический пример? Там утечка памяти...

S>Происходит так:
S>

    S>
  1. Вызывается operator[]. Он возвращает указатель.
    S>
  2. Возвращенный указатель увеличивается на 1 (адресная орифметика).
    S>
возвращается же T*, а не T*&, так что все нормально, утечки нет
Re[3]: operator[]
От: Кодт Россия  
Дата: 16.12.04 17:17
Оценка:
Здравствуйте, CyberZX, Вы писали:

CZX>возвращается же T*, а не T*&, так что все нормально, утечки нет


Утечка есть: память, выделенная в конструкторе, не прибивается в деструкторе. Операторы здесь не при чём.
Перекуём баги на фичи!
Re: operator[]
От: Аноним  
Дата: 17.12.04 10:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>есть код:


А>
А>template<typename T>
А>class Arr
А>{
А>   T* m_pData;
А>   int m_nRows;

А>public:
А>   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }
А>   T* operator[] (size_t n) { return m_pData + n*m_nRows;  }
А>};

А>//использование
А>Arr<int> arr(2, 2);
А>arr[2][1] = 3; //как выполняется опреатор [] в данной строке, какая последовательность???

А>



Этот код будет неправильно работать. Здесь не правильно высчитывается указатель в динамическом массиве:


Arr<int> arr(24, 3);
arr[20][1] = 3; //записываем неизвестно куда


в принципе реализация двумерного динамического массива данным приёмом невозможна
Re[2]: operator[]
От: 0xFADE США github.com/NotImplemented
Дата: 17.12.04 10:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>есть код:


А>>
А>>template<typename T>
А>>class Arr
А>>{
А>>   T* m_pData;
А>>   int m_nRows;

А>>public:
А>>   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }
А>>   T* operator[] (size_t n) { return m_pData + n*m_nRows;  }
А>>};

А>>//использование
А>>Arr<int> arr(2, 2);
А>>arr[2][1] = 3; //как выполняется опреатор [] в данной строке, какая последовательность???

А>>



А>Этот код будет неправильно работать. Здесь не правильно высчитывается указатель в динамическом массиве:


А>

А>Arr<int> arr(24, 3);
А>arr[20][1] = 3; //записываем неизвестно куда 
А>


А>в принципе реализация двумерного динамического массива данным приёмом невозможна


Это еще почему?
T* operator[] (size_t n) { return m_pData + n*m_nColumns;  }
Re[3]: operator[]
От: Аноним  
Дата: 17.12.04 11:03
Оценка:
Здравствуйте, 0xFADE, Вы писали:


FAD>Это еще почему?

FAD>
FAD>T* operator[] (size_t n) { return m_pData + n*m_nColumns;  }
FAD>


а что тут изменилось ?? для первого оператора [] будет выполнен сдвиг по второму значению "массива", и для второго [] по тому же значению.
А надо
для первого [] выполнить смещение по m_nRows а для второго [] по m_nColumns.
Re[4]: operator[]
От: Lapulya  
Дата: 17.12.04 13:41
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, 0xFADE, Вы писали:



FAD>>Это еще почему?

FAD>>
FAD>>T* operator[] (size_t n) { return m_pData + n*m_nColumns;  }
FAD>>


А>а что тут изменилось ?? для первого оператора [] будет выполнен сдвиг по второму значению "массива", и для второго [] по тому же значению.

А>А надо
А>для первого [] выполнить смещение по m_nRows а для второго [] по m_nColumns.

Ну ну ну.... погодите. После выполнения первого оператора [] в результате получим поинтер на T. а потом к нему применяется второй оператор []. Т.е. по сути запись

Arr<int> arr(2, 2);
arr[2][1] = 3;

можно переписать так

Arr<int> arr(2, 2);
int * buffer = arr[2];
buffer[1] = 3;

или так (что просто в данном случае нагляднее)

Arr<int> arr(2, 2);
int * buffer = arr[2];
*(++buffer) = 3;

никакого повторного вызова T* Arr::operator[] (size_t) тут нет
Re[5]: operator[]
От: Аноним  
Дата: 17.12.04 14:08
Оценка:
Здравствуйте, Lapulya, Вы писали:

L>Arr<int> arr(2, 2);

L>arr[2][1] = 3;

L>можно переписать так


L>Arr<int> arr(2, 2);

L>int * buffer = arr[2];
L>buffer[1] = 3;

L>или так (что просто в данном случае нагляднее)


L>Arr<int> arr(2, 2);

L>int * buffer = arr[2];
L>*(++buffer) = 3;

L>никакого повторного вызова T* Arr::operator[] (size_t) тут нет


Re: operator[]
От: Андрей Тарасевич Беларусь  
Дата: 18.12.04 21:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>есть код:


А>
А>template<typename T>
А>class Arr
А>{
А>   T* m_pData;
А>   int m_nRows;

А>public:
А>   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }
А>   T* operator[] (size_t n) { return m_pData + n*m_nRows; }
А>};

А>//использование
А>Arr<int> arr(2, 2);
А>arr[2][1] = 3; //как выполняется опреатор [] в данной строке, какая последовательность???

А>


Ну сначала стоит отметить, что в данном примере эмулируется двумерный массив 2 x 2. К такому массиву не разрешается доступаться по индексам [2][1], т.к. при этом первый индекс выходит за установленные пределы.

Предположим, что массив был сконструирован так

Arr<int> arr(3, 3);


Теперь вернемся к выражению

arr[2][1] = 3


В этой строке два обращения к оператору []. И это обращения к двум разным операторам []. Первое обращение — [2] — это обращение к перегруженному 'Arr<>::operator[]', второе обращение — [1] — это обращение ко втроенному оператору []. Последний применяется к результату первого.

Как известно, запись 'A[i]' для встроенного оператора [] эквивалентна записи '*(A + i)'. Таким образом твое выражение можно переписать вот так

*(arr[2] + 1) = 3


что эквивалентно

*(arr.operator[](2) + 1) = 3


Теперь подставим в это выражение код перегруженного оператора

*((arr.m_pData + 2 * arr.m_nRows) + 1) = 3


Т.к. при конструировании 'arr' значение 'm_nRows' было установлено в 3, получаем

*((arr.m_pData + 2 * 3) + 1) = 3


или просто

*(arr.m_pData + 7) = 3


что эквивалентно

arr.m_pData[7] = 3


Таким образом происходит трансляция пары "внешних" индексов (1 и 2 в нашем случае) в один индекс внутреннего массива (7 в нашем случае). Вот, собственно, и вся идея. Стоит заметить, что точно по такому же принципу работают встроенные массивы языков С/С++.
Best regards,
Андрей Тарасевич
Re: operator[]
От: Bell Россия  
Дата: 20.12.04 08:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>есть код:


А>
А>template<typename T>
А>class Arr
А>{
А>   T* m_pData;
А>   int m_nRows;

А>public:
А>   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }
А>   T* operator[] (size_t n) { return m_pData + n*m_nRows; }
А>};

А>//использование
А>Arr<int> arr(2, 2);
А>arr[2][1] = 3; //как выполняется опреатор [] в данной строке, какая последовательность???

А>


Запись arr[i][j] эквивалентна (arr[i])[j], т.е. сначала выполняется Arr::operator[], а затем к результату применяется встроенный operator[].
Однако в реализации Arr::operator[] есть ошибка: пусть имеем объект
Arr arr(10, 3);

Логично предположить, что запись arr[9][2] ссылается на третий элемент десятой строки (т.е. результирующий индекс в одномерном массиве должен быть равен 29). В предложенной же реализации arr[9][2] даст индекс 92.
Для вычисления "одномерного" индекса используется количество столбцов, а не строк:

arr[i][j] --> (m_pData + i*nColumns + j)
Любите книгу — источник знаний (с) М.Горький
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.