Ну это наверное акедемический пример? Там утечка памяти...
Происходит так: Вызывается operator[]. Он возвращает указатель.
Возвращенный указатель увеличивается на 1 (адресная орифметика).
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
S>Возвращенный указатель увеличивается на 1 (адресная орифметика).
Тьфу ты, чтобы не вводить в заблуждение, к адресу казателя прибавляется один раз размер в байтах типа указателя.
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Здравствуйте, Shady, Вы писали:
S>Здравствуйте, <Аноним>, Вы писали:
S>Ну это наверное акедемический пример? Там утечка памяти... S>Происходит так: S> S> Вызывается operator[]. Он возвращает указатель. S> Возвращенный указатель увеличивается на 1 (адресная орифметика). S>
возвращается же T*, а не T*&, так что все нормально, утечки нет
а что тут изменилось ?? для первого оператора [] будет выполнен сдвиг по второму значению "массива", и для второго [] по тому же значению.
А надо
для первого [] выполнить смещение по m_nRows а для второго [] по m_nColumns.
А>а что тут изменилось ?? для первого оператора [] будет выполнен сдвиг по второму значению "массива", и для второго [] по тому же значению. А>А надо А>для первого [] выполнить смещение по m_nRows а для второго [] по m_nColumns.
Ну ну ну.... погодите. После выполнения первого оператора [] в результате получим поинтер на T. а потом к нему применяется второй оператор []. Т.е. по сути запись
Ну сначала стоит отметить, что в данном примере эмулируется двумерный массив 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 в нашем случае). Вот, собственно, и вся идея. Стоит заметить, что точно по такому же принципу работают встроенные массивы языков С/С++.
Запись arr[i][j] эквивалентна (arr[i])[j], т.е. сначала выполняется Arr::operator[], а затем к результату применяется встроенный operator[].
Однако в реализации Arr::operator[] есть ошибка: пусть имеем объект
Arr arr(10, 3);
Логично предположить, что запись arr[9][2] ссылается на третий элемент десятой строки (т.е. результирующий индекс в одномерном массиве должен быть равен 29). В предложенной же реализации arr[9][2] даст индекс 92.
Для вычисления "одномерного" индекса используется количество столбцов, а не строк: