Недостатком массивов является то, что все данные в массиве обязательно должны быть одного типа. Для решения этой проблемы в языке C/C++ был введён тип данных **структура** (`struct`), который позволяет в одном контейнере хранить данные различных типов.  
**Описание, инициализация:**
```cpp
struct имя {
	тип1 имя_поля1;
	тип2 имя_поля2;
	...
	типN имя_поляN;
};
```
Пример:
```cpp
struct person {
	string name;
	int age;
}
person per;
per.name = "Nick";
per.age = 18;
```
Поля структуры могут быть любого типа данных, кроме типа самой структуры. Но может быть поле - указатель на данную структуру.  
**Пример:** Имеются данные, включающие в себя имя студента и результаты трёх экзаменов на сессии. Определить, какое количество студентов сдало сессию без троек.  
Данные об одном студенте будем хранить в структуре. Данные о всех студентах - в массиве.
```cpp
#include <iostream>
using namespace std;

struct student {
	string name;
	int m1, m2, m3;
};

int main() {
	const int n = 3;
	student a[n] = {
		{"Ann", 5, 5, 5}, 
		{"Anton", 4, 4, 4}, 
		{"Max", 3, 5, 5},
	} 
	
	int k = 0;
	for (int i = 0; i < n; i++) {
		if (a[i].m1 > 3 && a[i].m2 > 3 && a[i].m3 > 3) {
			cout << a[i].name << endl;
			k++;
		}
	}
	cout << k << endl;
	system("pause");
	return 0;
}
```
Часто при больших размерах структуры описываются не переменные структурного типа, а указатели на структуру. В этом случае можно существенно сэкономить память, создавая только необходимое количество структур, а по окончании работы с ними все их удалить.  
Пусть структура занимает в памяти 100 байт. Тогда массив из 10 структур будет занимать в памяти 1000 байт, а массив из 10 указателей - всего 40 байт.  
Обращение к полям указателей на структуру производится не через точку, а через стрелку (`->`).  
```cpp
#include <iostream>
using namespace std;

struct student {
		string name;
		int m1, m2, m3;
	};

int main() {
	int n = 3;
	student* a[n];
	
	for (int i = 0; i < n; i++) {
		cin >> a[i]->name;
		cin >> a[i]->m1;
		cin >> a[i]->m2;
		cin >> a[i]->m3;
	}
	
	int k = 0;
	for (int i = 0; i < n; i++) {
		if (a[i]->m1 > 3 && a[i]->m2 > 3 && a[i]->m3 > 3) {
			cout << a[i]->name << endl;
			k++;
			}
	}
	cout << k << endl;
	return 0;
}
```