Структуры. Часть 4. Структуры и функции. Передача структуры в функцию в среде CLR. Возврат структуры из функции
Содержание
- 1. Какие существуют способы передачи структуры в функцию?
- 2. Какие есть способы возврата структуры из функции?
- 3. Пример передачи native-структуры в функцию по значению
- 4. Пример передачи native-структуры в функцию по указателю
- 5. Как передать в функцию managed-структуру, которая объявлена с квалификатором ref? Пример
- 6. Как передать в функцию managed-структуру, которая объявлена с квалификатором value? Пример
- 7. Как реализовать возврат экземпляра native-структуры из функции? Пример
- 8. Пример возврата из функции указателя на native-структуру
- 9. Как возвратить экземпляр value-структуры из функции?
- 10. Пример возврата указателя (^) на value-структуру
- 11. Пример возврата из функции структуры, которая объявлена с квалификатором ref
- Связанные темы
Поиск на других ресурсах:
1. Какие существуют способы передачи структуры в функцию?
Существует 2 способа передачи native-структуры в функцию в качестве параметра:
- передача структуры по значению. При такой передаче делается копия структурной переменной в памяти. Если структура имеет большой размер, то такой способ неэффективен. Преимуществом этого способа есть то, что все манипуляции с копией структуры в функции не влияют на исходную переменную;
- передача указателя на структуру. В этом случае передается только указатель на структуру а не вся структура. Если структура занимает большой объем памяти, то такой способ обеспечивает быструю передачу значений структурной переменной в функцию. Это связано с тем, что передается только указатель на структуру. Недостатком этого способа есть то, что в функции случайно можно изменить значения исходной структурной переменной, в тех случаях когда это нежелательно.
2. Какие есть способы возврата структуры из функции?
Так же, как и при передаче структуры в функцию (см. п.1), существуют 2 способа возврата:
- возврат структуры по значению;
- возврат указателя на структуру.
Преимущества и недостатки каждого способа такие же, как описано в п. 1.
3. Пример передачи native-структуры в функцию по значению
Пусть в модуле «MyStruct.h» даны объявления native-структуры:
// native-структура, которая описывает точку на координатной плоскости struct MyPoint { int x; int y; };
Пусть в некотором классе объявляется функция EqualPoints(), которая сравнивает две точки на координатной плоскости. Функция возвращает true, если точки эквивалентны (равны между собой). В другом случае функция возвращает false.
// функция, которая сравнивает на равенство две точки public: bool EqualPoints(MyPoint p1, MyPoint p2) { bool f = false; if ((p1.x == p2.x) && (p1.y == p2.y)) f = true; return f; }
Тогда использование функции EqualPoints() может быть следующим:
// подключение модуля "MyStruct.h" #include "MyStruct.h" ... // передача native-структуры в функцию по значению bool f_equal; MyPoint pt1, pt2; // p1, p2 – переменные типа "структура" // заполнение значениями pt1.x = 23; pt1.y = 35; pt2.x = 23; pt2.y = 35; f_equal = this->EqualPoints(pt1, pt2); // f_equal = true pt1.x = 100; f_equal = EqualPoints(pt1, pt2);
4. Пример передачи native-структуры в функцию по указателю
Пусть задана native-структура:
// native-структура struct MyPoint { int x; int y; };
Ниже реализована функция, которая сравнивает на равенство значения структурных переменных. Функция получает указатель на структуру.
// передача указателя на структуру MyPoint bool EqualPointsP(MyPoint * p1, MyPoint * p2) { bool f = false; if ((p1->x == p2->x) && (p1->y == p2->y)) f = true; return f; }
Программный код, демонстрирующий использование функции EqualPoints().
// Передача структуры по указателю MyPoint p1; MyPoint p2; bool f_equal; p1.x = 28; p1.y = 35; p2.x = 28; p2.y = 35; f_equal = EqualPointsP(&p1, &p2); // f_equal = true p2.y = 100; f_equal = EqualPointsP(&p1, &p2); // f_equal = false
5. Как передать в функцию managed-структуру, которая объявлена с квалификатором ref? Пример
Пусть задана следующая ref-структура.
// ref-структура ref struct MyPointRef { int x; int y; };
Структуры с квалификатором ref есть структурами ссылочного типа. Для таких структур память должна выделяться с помощью утилиты gcnew. Поэтому, в функцию можно передать только ссылку на такие структуры.
Пусть дана функция LengthRef(), которая определяет длину линии, которая соединяет 2 точки. Функция получает две ref-структуры в качестве параметров.
// Функция, определяющая длину между двумя точками float LengthRef(MyPointRef ^p1, MyPointRef ^p2) { float l; l = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return l; }
Использование функции LengthRef() в некотором программном коде.
// передача ref-структуры в функцию MyPointRef ^ pt1; MyPointRef ^ pt2; float len; // выделение памяти для ref-структур pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заполнение ref-структур значениями pt1->x = 35; pt1->y = 35; pt2->x = 40; pt2->y = 40; len = LengthRef(pt1, pt2); // len = 7.071068
6. Как передать в функцию managed-структуру, которая объявлена с квалификатором value? Пример
Managed-структуру, объявленную с квалификатором value можно передать в функцию одним из двух способов:
- по значению;
- по указателю.
Ниже приведены оба способа для value-структуры MyPointValue, которая имеет следующее объявление.
// value-структура value struct MyPointValue { int x; int y; };
Способ 1.
Пусть задана функция LengthValue(), определяющая расстояние между двумя точками. Функция получает входным параметром две структуры типа MyPointValue. Структуры передаются как параметр-значение.
// определение расстояния между двумя точками float LengthValue(MyPointValue p1, MyPointValue p2) { float len; len = (float)Math::Sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); return len; }
Пример использования функции LengthValue() в другом программном коде.
// передача value-структуры по значению MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 35; pt1.y = 50; pt2.x = 40; pt2.y = 55; len = LengthValue(pt1, pt2); // len = 7.071068
Способ 2. Передача структуры по указателю.
Пусть задана функция LengthValue(), получающая два указателя на структуры типа MyPointValue.
// функция получает указатель на value-структуру float LengthValueP(MyPointValue *p1, MyPointValue *p2) { float len; len = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return len; }
Использование функции LengthValue() в программе.
// передача value-структуры по указателю MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 0; pt1.y = 0; pt2.x = 10; pt2.y = 10; len = LengthValueP(&pt1, &pt2); // len = 14.14214
7. Как реализовать возврат экземпляра native-структуры из функции? Пример
Возвратить native-структуру можно:
- по значению;
- по адресу.
Пусть задана структура MyPoint
// native-структура struct MyPoint { int x; int y; };
Пусть в программе реализована функция GetCenterLine(), которая вычисляет координаты середины отрезка, соединяющего 2 точки. Функция получает 2 параметра – координаты концов отрезка.
// функция, возвращающая native-структуру // функция вычисляет координаты середины отрезка MyPoint GetCenterLine(MyPoint p1, MyPoint p2) { MyPoint res; res.x = (p1.x + p2.x)/2; res.y = (p1.y + p2.y)/2; return res; }
Демонстрация возврата native-структуры по значению.
MyPoint pt1; MyPoint pt2; MyPoint res; // результат, память уже выделена pt1.x = 30; pt1.y = 20; pt2.x = 36; pt2.y = 40; res = GetCenterLine(pt1, pt2); // res - координаты середины отрезка
8. Пример возврата из функции указателя на native-структуру
Пусть задана структура MyPoint
// native-структура struct MyPoint { int x; int y; };
Пусть реализована функция GetCenterLine(), которая получает 2 точки и возвращает указатель на структуру. В теле функции реализовано выделение памяти для структуры оператором new.
MyPoint * GetCenterLine(MyPoint p1, MyPoint p2) { MyPoint * res; // указатель на структуру MyPoint // выделение памяти для структуры res = new MyPoint; // вычисление середины отрезка - заполнение значениями resP->x = (p1.x + p2.x)/2; resP->y = (p1.y + p2.y)/2; return res; }
Демонстрация работы с функцией GetCenterLine().
// возвращение native-структуры по указателю MyPoint * resPt; // указатель на структуру – память для структуры еще не выделена MyPoint pt1, pt2; // экземпляры структуры pt1.x = 28; pt1.y = 40; pt2.x = 38; pt2.y = 50; // вызов функции GetCenterLine() // для указателя resPt память выделяется внутри функции resPt = GetCenterLine(pt1, pt2); // проверка int d; d = resPt->x; // d = 33 d = resPt->y; // d = 45
9. Как возвратить экземпляр value-структуры из функции?
Если в среде CLR описана структура с квалификатором value, то возврат экземпляра такой структуры из функции ничем не отличается от возвращения native-структуры (см. п. 7.).
10. Пример возврата указателя (^) на value-структуру
Если структура объявлена с квалификатором value, то функция может возвращать указатель на эту структуру. Допускается использование двух видов указателей:
- классического указателя, который обозначается символом ‘*’. Возврат такого указателя из функции не отличается от возврата указателя на native-структуру (см. п. 8);
- указателя, предназначенного для работы с объектами среды CLR. Такой указатель обозначается символом ‘^‘. Память для такого указателя выделяется утилитой gcnew. Ниже приведен пример возврата из функции такого указателя на value-структуру.
Пусть объявлена структура с квалификатором value
// value-структура value struct MyPointValue { int x; int y; };
Пусть нужно реализовать функцию GetCenterLineVP(), которая получает 2 точки и возвращает указатель на результирующую value-структуру. Результирующая структура содержит координаты центра отрезка, который соединяет точки. Функция имеет следующий вид:
// функция возвращает указатель на value-структуру MyPointValue ^ GetCenterLineVP(MyPointValue p1, MyPointValue p2) { MyPointValue ^ pv; // указатель на структуру MyPointValue pv = gcnew MyPointValue; pv->x = (p1.x + p2.x)/2; pv->y = (p1.y + p2.y)/2; return pv; }
Демонстрация вызова функции из другого программного кода:
// создание экземпляров структур с инициализацией MyPointValue pt1 = { 20, 30 }; MyPointValue pt2 = { 40, 60 }; // указатель на структуру MyPointValue MyPointValue ^ resPt; // вызов функции GetCenterLineVP() // внутри функции выделяется память для структуры, // на которую указывает resPt resPt = GetCenterLineVP(pt1, pt2); // проверка int d; d = resPt->x; // d = 30 d = resPt->y; // d = 45
11. Пример возврата из функции структуры, которая объявлена с квалификатором ref
Для структуры, которая объявлена с квалификатором ref есть определенные особенности использования. Такая структура есть структурой ссылочного типа. Поэтому функция должна возвращать ссылку на такую структуру (указатель на структуру). Возвратить экземпляр ref-структуры (по значению) из функции не удастся (см. п. 5).
Пусть объявлена структура
// ref-структура ref struct MyPointRef { int x; int y; };
Тогда функция, которая получает 2 точки в качестве параметров и находит центр между двумя точками будет иметь приблизительно следующий вид:
// функция, возвращающая ref-структуру MyPointRef ^ GetCenterLineRef(MyPointRef ^p1, MyPointRef ^p2) { MyPointRef ^resPt; // выделение памяти для указателя resPt resPt = gcnew MyPointRef; // заполнение значениями полей указателя resPt->x = (p1->x + p2->x)/2; resPt->y = (p1->y + p2->y)/2; return resPt; }
Демонстрация использования функции в другом программном коде.
// указатели на ref-структуру MyPointRef ^pt1; MyPointRef ^pt2; MyPointRef ^resPt; // выделение памяти для указателей pt1, pt2 pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заполнение значениями pt1->x = 20; pt1->y = 20; pt2->x = 30; pt2->y = 40; // вызов функции GetCenterLineRef() // память для указателя resPt выделяется внутри функции resPt = GetCenterLineRef(pt1, pt2); // проверка int d; d = resPt->x; // d = 25 d = resPt->y; // d = 30
Связанные темы
- Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
- Структуры. Часть 2. Выделение памяти для структуры. Вложенные структуры. Массивы native-структур
- Структуры. Часть 3. Работа с managed-структурами в среде CLR. Квалификаторы ref и value. Объявление структурных переменных. Массивы managed-структурных переменных. Инициализация managed-структур
- Функции. Часть 1. Описание функции. Фактические и формальные параметры. Передача параметров в функцию по значению и по адресу. Прототип функции
- Функции. Часть 2. Функции и массивы. Передача одномерного и многомерного массива в функцию. Передача структуры и класса в функцию