2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 operator [][]
Сообщение29.11.2009, 15:42 


23/12/08
245
Украина
Ну собственно я хочу сделать клас алгебраическа матрица, но с зарание неизвестным размером, но так как в с++ многомерные матрици нельязя параметоризовать по всем измерениям, то я решил сделать хранить данные в обычном массиве, и мне хотелось бы иметь удобный интерфейс к его елементам, а удобно мне будет если я смогу записать чтото типа
Код:
matrix[2][1] = 1;

Я придумал только два варианта :
1) исползовать функциональный подход( просто, легко, и некрасиво)
2) повводить промежуточные класы столпцов,и строк, написать для них приват операторы(прекрасный интерфес, но весьма громоздкий механизм)

Подскажите как это сделать попроще. Или хотябы прокоментируйте пункт 2).

 Профиль  
                  
 
 Re: operator [][]
Сообщение29.11.2009, 16:23 
Заслуженный участник


27/04/09
28128
Ну, классы и столбцов, и строк вводить не надо. Только строк. Примерно так чтоб было:
Используется синтаксис C
MatrixRow operator[] (Matrix m, unsigned i);
double& operator[] (MatrixRow m, unsigned i);

Может, кто-нибудь (не я :) ) знает ещё какой-нибудь метод, кроме описанных вами.
В классе строки будет ссылка на массив, который лежит в классе Matrix, и индекс этой самой строки. Больше ничего и не надо. Только не пойму, зачем объявлять оператор [] у строки private? Ведь к нему не будет доступа. Нужен public!

Я не очень хорошо знаю си, надеюсь, не попутал ничего.

 Профиль  
                  
 
 Re: operator [][]
Сообщение29.11.2009, 16:52 
Заслуженный участник


04/05/09
4582
Можно ещё из первого оператора возвращать простой указатель на элементы строк.

 Профиль  
                  
 
 Re: operator [][]
Сообщение29.11.2009, 17:11 


02/07/08
322
Можно переопределить оператор () для получения двухиндексной адресации.
С другой стороны, вы не указали, с какой целью разрабатывается класс. Вообще операция получения строки или столбца матрица является совершенно нормальной, и если можно реализовать это всё так, чтобы возвращалась ссылка на кого-то из них (столбец, строку), то логично это сделать. Ещё с другой стороны всё равно вряд ли получится очень эффективно реализовать операции над матрицами, чтобы не возвращать их по значению всюду, поэтому такая оптимизация может оказаться совершенно не нужной.

 Профиль  
                  
 
 Re: operator [][]
Сообщение29.11.2009, 17:33 
Заслуженный участник


27/04/09
28128
Можно как [R][C], так и (R, C) сделать, кстати! Чтобы на любой вкус! :D

 Профиль  
                  
 
 Re: operator [][]
Сообщение29.11.2009, 18:53 


23/12/08
245
Украина
arseniiv в сообщении #266368 писал(а):
Ну, классы и столбцов, и строк вводить не надо. Только строк. Примерно так чтоб было:
Используется синтаксис C
MatrixRow operator[] (Matrix m, unsigned i);
double& operator[] (MatrixRow m, unsigned i);

Может, кто-нибудь (не я :) ) знает ещё какой-нибудь метод, кроме описанных вами.
В классе строки будет ссылка на массив, который лежит в классе Matrix, и индекс этой самой строки. Больше ничего и не надо. Только не пойму, зачем объявлять оператор [] у строки private? Ведь к нему не будет доступа. Нужен public!

Я не очень хорошо знаю си, надеюсь, не попутал ничего.

Да я опечатался, я имел ввиду ввести свой приват клас строка.
Кстати наверно так и сделаю, ведь строки мне всёравно надо, клас ведь алгебраический.

 Профиль  
                  
 
 Re: operator [][]
Сообщение29.11.2009, 21:52 
Заслуженный участник


26/07/09
1559
Алматы
2Nerazumovskiy
Цитата:
в с++ многомерные матрици нельязя параметоризовать по всем измерениям

Что вы имели ввиду? :) Матрицы на основе обычных указателей могут иметь любое количество измерений и любые размеры по ним. Можете реализовать библиотеку поддержки тензорного исчисления, к примеру. Или я вас неправильно понял? Я имел ввиду, что размеры-то можно менять динамически, перераспределяя память...

Цитата:
исползовать функциональный подход

Это как? Или вы говорите о круглых скобках?

Цитата:
повводить промежуточные класы столпцов,и строк

Вообще, если вы уж решили изобретать велосипед, то можно попробовать реализовать шаблонный класс только для векторов (в смысле лин. алгебры), а матрицу просто хранить как вектор векторов, дешево и сердито. :)

Хотя, понятно, что лучше иметь отдельный класс, инкапсулирующий матрицы. Это может пригодиться при оптимизации операций над матрицами специального вида, ну типа разреженных там всяких...

Если нужна многомерность матриц, то можно поэкспериментировать с "рекурсивными" типами данных, представляя матрицу в виде вектора матриц, имеющих на единицу меньшую размерность.

P.S.: Ну и конечно же не забывайте про шаблоны выражений (expression templates).
P.P.S.: В сторону Blitz++ смотрели?

 Профиль  
                  
 
 Re: operator [][]
Сообщение30.11.2009, 00:25 


23/12/08
245
Украина
2Circiter
Да судя по всему Blitz++ шикарная библиотека, но у меня лабораторная сформулирована так : никаких сторонних модулей, кроме стандартной библиотеки :)

Так, ну этот хитрый механиз с промежуточным класом(Row) я уже реализовал, но не всё так харашо как хотелось бы,
собственно operator[][] работает на ура, а вот при попытке прицепить к строкам арифметические операции наблюдаю очень упорное противостояние, причом настолько упорное что даже немогу понять чтоже ему не нравиться(строчку с ошибкой я нашол, а вот причину так и непонял), наверно буду использовать для получения юзабельных строк чтото вроде метода $.at()$ (именно его я имел ввиду когда говорил о функциональном подходе).

P.S.Если хтото обяснит почемуже арифметки со строками в данном случае невозможна через клас Row(или обяснит как ее таки сделать) это будет весьма познавательно. (для меня так точно)



Для тех кому интересно:
1) исходний код
2) под арифметикой строк я имею ввиду виражение:
Код:
Matrix a(/*size =*/ 3);
cin>>a;
a[0] = a[1] + a[2];

ошибка вилетает в операторе =

_______________________________
Написав пост выше я думал что у меня ничего не работает, но внезапно закоментировал две строчки и всё заработало правильно, что меня повергло в шок, ведь я даже могу обяснить почему оно не должно работать так как работает. И кстати говоря я даже нашол случай когда оно не работает, но опятьже обяснить немогу.

______
закоментировал я строчки тут:
Код:
Row& Row::operator =(const Row & a)
{
   if( this == &a) return *this;
   //delete[] m;
//   m = new Frac[a.s];
   s = a.s;
   for(int i=0;i<s;i++)
   {
      m[i] = a.m[i];
   }
   return *this;
}

и теперь по идее я несмогу дублировать данные, и скопированные обэкты будут указывать в одно и тоже место. Но при этом если я пишу
Код:
Matrix a,b;
   cout<<"Enter Matrix  3*3"<<endl;
   cin>>a;
   cout<<a;

   b[0] = a[0];
   a[0] = a[1]+ a[0];
   cout<<"a ="<<a<<endl;
   cout<<b;

а сделать этот код неработающим можно просто написав так:
Код:
Matrix a,b,c;//все матрици по умолчанию 3*3, с изначально нулевыми елементами(мне так удобней)
   cout<<"Enter Matrix  3*3"<<endl;
   cin>>a;
   cout<<a;
b =c;
   b[0] = a[0];
   a[0] = a[1]+ a[0];
   cout<<"a ="<<a<<endl;
   cout<<b;



P.P.S. собственно исходний код всего этого чудища: http://dl.dropbox.com/u/2375611/Matrix.rar

-- Вс ноя 29, 2009 23:27:27 --

arseniiv в сообщении #266400 писал(а):
Можно как [R][C], так и (R, C) сделать, кстати! Чтобы на любой вкус! :D

А можна пример как это сделать, ато я вот тут уже третье колесо к велосипеду изобретаю.

 Профиль  
                  
 
 Re: operator [][]
Сообщение30.11.2009, 17:01 


23/12/08
245
Украина
Вобщемто я уже розобрался, идея была в том что я просто забыл для матриц сделать оператор = :)

 Профиль  
                  
 
 Re: operator [][]
Сообщение30.11.2009, 19:46 
Заслуженный участник


27/04/09
28128
Nerazumovskiy в сообщении #266608 писал(а):
А можна пример как это сделать, ато я вот тут уже третье колесо к велосипеду изобретаю.

Ну, это я имел ввиду, что можно и метод через промежуточные строчки, и перегруженный () использовать. Кому не понравятся строчки, пусть использует () :D
Кстати, я думал, т.к. чтроки привязаны к матрице, их не надо никуда удалять, а вы сначала удаляли и пересоздавали. Матрица-то испортится от таких манипуляций! У вас что хранится в строке? Лучше бы она хранила две вещи: указатель на "свой" дин. массив из матрицы, которая её создала и индекс. Тогда можно вот как поправить:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
// поле linked - логическое: присоединена ли строка к матрице (или же она "плавает". Например, такая нужна для суммы-разности строк)
// поле row - указатель на строку из матрицы, если создана одним конструктором (там параметрами будут индекс и "родительская" матрица) ИЛИ динамически выделенная в другом конструкторе строка (там параметр - длина строки). Соответственно конструктору поставится свойство linked.
// поле len должно хранить длину строки
// в деструкторе, если !linked, строка удаляется
// у вас тут какая-то игра со звёздочками была, хотя тут же ясно указан тип &, так что ничего не надо
Row &Row::operator=(const Row &a)
{
  if (row == a.row) return this;
  if (linked && len != a.len) {
    // тут генерьте ошибку. Не пристало матрицам подстраиваться под чужие строчки ; )
  }
  len = a.len;
  for (int i = 0; i < len; i++) row[i] = a.row[i];
  return this;
}
// пример операции +
Row &Row::operator+(const Row &a, const Row &b)
{
  unsigned len;
  if ((len = a.len) != b.len) {
    // опять же, не пристало
  }
  Row *r = new Row(len); // второй конструктор, плавучая строка
  for (int i = 0; i < len; i++) r.row[i] = a.row[i] + b.row[i];
  return r;  
}
 
Надеюсь, снова ничего не напутал.

-- Пн ноя 30, 2009 22:50:52 --

(Только, конечно, operator+= надо реализовывать не через operator+. А то будет создаваться временная строка и уничтожаться. Он будет совершенно похож на operator= за исключением строки с присваиванием, которое будет заменено на +=.)

 Профиль  
                  
 
 Re: operator [][]
Сообщение30.11.2009, 21:21 
Заслуженный участник


27/04/09
28128
Кстати, в operator+ параметры и результат -ссылки не нужны, надо их сделать простыми. (Можно и так оставить, просто "лишний груз" будет.) :)

 Профиль  
                  
 
 Re: operator [][]
Сообщение01.12.2009, 12:09 


02/07/08
322
Они не просто не нужны, но и категорически противопоказаны. Во-первых, они довольно неудобны с точки зрения интерфейса (например, если будет оператор == на рядах, то мы не сможем написать if (a == b + c)), результатом работы оператора является исключительно lhs-value. Во-вторых, и главное, у вас с таким подходом - возвращение ссылки на созданный в куче объект - произойдёт утечка памяти: если у вас были объекты Row row1, row2, row3, то после вызова row1 = row2 + row3 переменная row1 будет ссылаться на новый объект, а ссылка на старый потеряется, и никто не займётся его удалением. Отслеживать это вручную - непосильная задача.
Способы этого избежать есть разные. Простейший из них - всё возвращать в программе по значению. Многие компиляторы имеют return value optimization, поэтому можно приступить к оптимизированию этого только после того, как вы произвели замеры и выяснили, что текущей скорости вам недостаточно, а медленным элементом является возвращение значений.
Остальные способы гораздо более трудоемкие и сложные в реализации, они связаны с другим проектированием системы классов - введением дескрипторов объектов или работой с автоматическими указателями от объектов. Наверное, есть и другие способы, но я их не знаю.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group