Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Август 29, 2009, 13:27



Название: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 13:27
Добрый день

struct Matrix {
  double m[4][4];
};

void InvertMatrix( Matrix * theInvertedMatrix, Matrix theSourceMatrix );

Почему программист выбрал такой способ передачи параметров?


Название: Re: Передача параметров/аргументов
Отправлено: BRE от Август 29, 2009, 13:36
Добрый день

struct Matrix {
  double m[4][4];
};

void InvertMatrix( Matrix * theInvertedMatrix, Matrix theSourceMatrix );

Почему программист выбрал такой способ передачи параметров?
Я так понимаю, что это C.

Думаю программист хотел указать, что исходная (theSourceMatrix) в функции не изменяется, в отличии от результирующей (theInvertedMatrix).


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 13:43
Я так понимаю, что это C.

typedef struct {
  double m[4][4];
} Matrix;

Вот это было бы "С"  :)

Думаю программист хотел указать, что исходная (theSourceMatrix) в функции не изменяется, в отличии от результирующей (theInvertedMatrix).
Тогда почему не

void InvertMatrix( Matrix * theInvertedMatrix, const Matrix4 * theSourceMatrix );

?


Название: Re: Передача параметров/аргументов
Отправлено: BRE от Август 29, 2009, 13:49
Тогда почему не

void InvertMatrix( Matrix * theInvertedMatrix, const Matrix4 * theSourceMatrix );

?
Вот уж не знаю, это скрыто в голове того программиста. :)
Я бы вообще скорее всего так объявил:
void InvertMatrix( Matrix &theInvertedMatrix, const Matrix &theSourceMatrix );


Название: Re: Передача параметров/аргументов
Отправлено: BRE от Август 29, 2009, 13:52
Часто бывает, что используются куски кода из других библиотек. Вполне возможно программист просто перенес функции работы с матрицами из одной из таких библиотек к себе в проект...  ???


Название: Re: Передача параметров/аргументов
Отправлено: lit-uriy от Август 29, 2009, 14:01
>>void InvertMatrix( Matrix &theInvertedMatrix, const Matrix &theSourceMatrix );
А вот в Си, по ссылке ещё нельзя передавать, это стало возможно в С++

>>Вот это было бы "С"
Первым способом многие компиляторы едят.


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 29, 2009, 14:06
Код
C
void InvertMatrix( Matrix * theInvertedMatrix, Matrix theSourceMatrix ) {
 ...
 ...
 *theInvertedMatrix = theSourceMatrix;
}
 


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 14:36
Часто бывает, что используются куски кода из других библиотек. Вполне возможно программист просто перенес функции работы с матрицами из одной из таких библиотек к себе в проект...  ???
Ничего он не переносил, программист классный (хоть и из Колорадо). Конечно. можно написать как Вы или я предложили. Но у него сделано проще и лучше.


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 29, 2009, 15:13
Ну и какой здесь скрытый смысл?
Ради какой оптимизации это сделано?


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 15:48
Ну и какой здесь скрытый смысл?
Ради какой оптимизации это сделано?
Намекнуть/подсказать ?  :)


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 29, 2009, 16:11
Ну и какой здесь скрытый смысл?
Ради какой оптимизации это сделано?
Намекнуть/подсказать ?  :)
Без контекста использования ничего толкогого о таком способе сказать нельзя.
Так что рассказывай :)


Название: Re: Передача параметров/аргументов
Отправлено: zenden от Август 29, 2009, 16:25
Чтоб можно было указать исходную матрицу в качестве результирующей, и не думать что у функции внутри.


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 16:27
Без контекста использования ничего толкогого о таком способе сказать нельзя.
Так что рассказывай :)
Подумайте как было бы удобно (и неудобно) вызывать функцию InvertMatrix. Какие проблемы/неудобства могут возникнуть при использовании классического

void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );

?


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 16:29
Чтоб можно было указать исходную матрицу в качестве результирующей.
Прямое попадание. все правильно. Поздравляю! 


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 29, 2009, 16:31
Чтоб можно было указать исходную матрицу в качестве результирующей.
Прямое попадание. все правильно. Поздравляю!  
Ну и в чем прикол? Не вижу особой разницы.
Разве что
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
Лучше чем
void InvertMatrix( Matrix * theInvertedMatrix, Matrix theSourceMatrix );
с точки зрения оптимизации.
В последнем случае - может возникнуть лишнее копирование структуры


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 17:14
Ну и в чем прикол? Не вижу особой разницы.
Разве что
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
Лучше чем
void InvertMatrix( Matrix * theInvertedMatrix, Matrix theSourceMatrix );
с точки зрения оптимизации.
В последнем случае - может возникнуть лишнее копирование структуры

Для приколов есть другие threads. Здесь же (увы) прийдется все разжевывать. Часто (в большинстве случаев)  нужно инвертировать матрицу "на месте". В этом случае theInvertedMatrix и theSourceMatrix указывают на тот же адрес. При передаче обеих матриц по адресу/ссылке надо это предусмотреть:

Код:
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix )
{
   Matrix temp;
   if (theInvertedMatrix == theSourceMatrix) {
     temp = *theSourceMatrix;
     theSourceMatrix = &temp;
   }
  
// теперь инвертируем Гауссом и.т.п.
   ....
}

А он просто сказал компилятору то же сделать  и спокойно вызывает

Код:
Matrix M = ...
...
InvertMatrix(&M, M):


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 29, 2009, 18:28
Как я и сказал:
void InvertMatrix( Matrix * theInvertedMatrix, Matrix theSourceMatrix );
ничего особенного, тем более оптимального нет, только лишнее копирование матрицы!

Правильнее и наиболее оптимально:
Код:
void InvertMatrix(Matrix& theInvertedMatrix, const Matrix* theSourceMatrix=NULL)
{
   if (theSourceMatrix && theSourceMatrix != &theInvertedMatrix) {theInvertedMatrix= *theSourceMatrix;}

// invert matrix  theInvertedMatrix

}

InvertMatrix(M) <=> InvertMatrix(M, &M)  <=>  InvertMatrix(M, NULL) - и нет лишнего копирования матрицы
InvertMatrix(M, &N) - где M != N, одно копирование матрицы

Я не знаю алгоритма которым в данном случае инвертируется матрица.
То что я привел оптимально для случая когда работа может быть произведена с одной матрицей, если это не так то я не прав.
В любом случае припостановке задачи нужно описывать исходные условия.


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 29, 2009, 19:03
Правильнее и наиболее оптимально:
Код:
void InvertMatrix(Matrix& theInvertedMatrix, const Matrix* theSourceMatrix=NULL)
{
   if (theSourceMatrix && theSourceMatrix != &theInvertedMatrix) {theInvertedMatrix= *theSourceMatrix;}

// invert matrix  theInvertedMatrix

}
Так сходу не получается  :) Defaulrt NULL не имеет смысла, нет исходной матрицы - нечего инвертировать. Присвоение theInvertedMatrix ничего не дает т.к. theInvertedMatrix должна (довольно тщательно) вычисляться. Логика мало изменилась со времен Аристотеля - и она столь же неумолима (знание классов мало помогает :-)) 


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 29, 2009, 19:24
Так сходу не получается  :) Defaulrt NULL не имеет смысла, нет исходной матрицы - нечего инвертировать. Присвоение theInvertedMatrix ничего не дает т.к. theInvertedMatrix должна (довольно тщательно) вычисляться. Логика мало изменилась со времен Аристотеля - и она столь же неумолима (знание классов мало помогает :-))  
Я написал что не знаю используемого алгоритма для инвертирования и в данном случае это не важно.
Важно оно производиться с использаванием одной или двух матриц.
Если одной, то выше я привел оптимальный вариант.
Если двух(требуется неизменненная исходная матрица), то лучше будет так:
Код:
void InvertMatrix(Matrix& theInvertedMatrix, const Matrix* theSourceMatrix=NULL)
{
   const Matrix* src;
   if (theSourceMatrix && theSourceMatrix != &theInvertedMatrix) {
     src = theSourceMatrix;
   } else {
     src = new Matrix(theInvertedMatrix); //copy theInvertedMatrix
   }

// invert matrix
// use src instead theSourceMatrix

  if(src != theSourceMatrix) {delete src;}
}

Опять же имем
InvertMatrix(M) <=> InvertMatrix(M, &M)  <=>  InvertMatrix(M, NULL) - инвертирование самой себя
InvertMatrix(M, &N) - где M != N, нет лишнего копирования матрицы

=====

Default NULL - для простой записи в случае инвертирования самой себя  - InvertMatrix(M), вместо InvertMatrix(M, &M)


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 30, 2009, 10:00
Вызов new/delete гораздо дороже чем передача структуры по значению. Само инвертирование довольно сложное, больше 100 строк, поэтому надо держать его в 1 функции. Разумеется, Ваш и мой варианты будут работать, но согласитесь: ковбой из Колорадо написал короче/проще  :)   


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 30, 2009, 10:42
Вызов new/delete гораздо дороже чем передача структуры по значению. Само инвертирование довольно сложное, больше 100 строк, поэтому надо держать его в 1 функции. Разумеется, Ваш и мой варианты будут работать, но согласитесь: ковбой из Колорадо написал короче/проще  :)   
Не соглашусь, здесь нет ничего особенного, это дело вкуса.
Я бы однозначно оставил свой вариант объвления он мне кажется удобнее в использовании.
void InvertMatrix(Matrix& theInvertedMatrix, const Matrix* theSourceMatrix=NULL);
А написать лишнюю проверку не проблема, можно и не заморочиваться с псевдооптимизацией, а тупо создавать копию нужной матрицы.
Код:
   Matrix src;
   if (theSourceMatrix && theSourceMatrix != &theInvertedMatrix) {
     src = theSourceMatrix;
   } else  {
     src = theInvertedMatrix;
   }


Название: Re: Передача параметров/аргументов
Отправлено: Winstrol от Август 30, 2009, 23:21
Часто (в большинстве случаев)  нужно инвертировать матрицу "на месте".
Не так уж и часто. В мат. библиотеках (BLAS,LAPACK)  функции инвертации "на месте" вовсе нет.



Название: Re: Передача параметров/аргументов
Отправлено: Winstrol от Август 30, 2009, 23:26
Чтоб можно было указать исходную матрицу в качестве результирующей.
Прямое попадание. все правильно. Поздравляю! 
А почему не пара функций?

void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
Matrix InvertMatrix(const Matrix * theSourceMatrix )


Название: Re: Передача параметров/аргументов
Отправлено: spectre71 от Август 31, 2009, 00:48
А почему не пара функций?
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
Matrix InvertMatrix(const Matrix * theSourceMatrix )

Matrix InvertMatrix(const Matrix * theSourceMatrix )
Хуже чем:
InvertMatrix(Matrix * theMatrix) или InvertMatrix(Matrix & theMatrix)
Поскольку получаем дополнительное копирование матрицы при возврате.
=====
Далее: пара функций
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
void InvertMatrix(Matrix * theMatrix)
Не лучше чем
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix=NULL);
Поскольку
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix=NULL);
перекрывает эту пару!
Кроме того, для
void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
все равно необходимо проверять(и правильно обрабатывать) случай, когда theInvertedMatrix == theSourceMatrix


Название: Re: Передача параметров/аргументов
Отправлено: Winstrol от Август 31, 2009, 13:46
InvertMatrix(Matrix * theMatrix) или InvertMatrix(Matrix & theMatrix)
Поскольку получаем дополнительное копирование матрицы при возврате.
Для такого простого случая, когда Matrix - структура в стиле C без плюсов, слава Богу, не будет.


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 31, 2009, 15:08
А почему не пара функций?

void InvertMatrix( Matrix * theInvertedMatrix, const Matrix * theSourceMatrix );
Matrix InvertMatrix(const Matrix * theSourceMatrix )

Потому что само инвертирование довольно длинное/сложное и писать его дважды нехорошо


Название: Re: Передача параметров/аргументов
Отправлено: BlackTass от Август 31, 2009, 17:17
Потому что само инвертирование довольно длинное/сложное и писать его дважды нехорошо
а кто-то говорил о дублировании кода разве? просто одна вызывает другую


Название: Re: Передача параметров/аргументов
Отправлено: Igors от Август 31, 2009, 17:36
а кто-то говорил о дублировании кода разве? просто одна вызывает другую
Кто ж спорит, конечно можно. Но как ни крути, а строк 5 Вам для этого прийдется написать. И делать эти строки будут именно то что делает передача структуры по значению  :)