Введение в язык Си++

Структуры


Вектор есть совокупность элементов одного типа; struct является совокупностью элементов (практически) произвольных типов. Например:

struct address { // почтовый адрес char* name; // имя "Jim Dandy" long number; // номер дома 61 char* street; // улица "South Street" char* town; // город "New Providence" char* state[2]; // штат 'N' 'J' int zip; // индекс 7974 }

определяет новый тип, названный address (почтовый адрес), состоящий из пунктов, требующихся для того, чтобы послать кому-нибудь корреспонденцию (вообще говоря, address не является достаточным для работы с полным почтовым адресом, но в качестве примера достаточен). Обратите внимание на точку с запятой в конце; это одно из очень немногих мест в C++, где необходимо ставить точку с запятой после фигурной скобки, поэтому люди склонны забывать об этом.

Переменные типа address могут описываться точно также, как другие переменные, а доступ к отдельным членам получается с помощью операции . (точка). Например:

address jd; jd.name = "Jim Dandy"; jd.number = 61;

Запись, которая использовалась для инициализации векторов, можно применять и к переменным структурных типов. Например:

address jd = { "Jim Dandy", 61, "South Street", "New Providence", {'N','J'}, 7974 };

Однако обычно лучше использовать конструктор (#5.2.4). Заметьте, что нельзя было бы инициализировать jd.state строкой "NJ". Строки оканчиваются символом '\0', поэтому в "NJ" три символа, то есть на один больше, чем влезет в jd.state.

К структурным объектам часто обращаются посредством указателей используя операцию -. Например:

void print_addr(address* p) { cout name number street town state[0]) state[1]) zip

Объекты типа структур можно присваивать, передавать как параметры функции и возвращать из функции в качестве результата. Например:

address current;

address set_current(address next) { address prev = current; current = next; return prev; }

Остальные осмысленные операции, такие как сравнение (== и !=) не определены. Однако пользователь может определить эти операции; см.


Размер объекта структурного типа нельзя вычислить просто как сумму его членов. Причина этого состоит в том, что многие машины требуют, чтобы объекты определенных типов выравнивались в памяти только по некоторым зависящим от архитектуры границам (типичный пример: целое должно быть выравнено по границе слова) или просто гораздо более эффективно обрабатывают такие объекты, если они выравнены в машине. Это приводит к "дырам" в структуре. Например, (на моей машине) sizeof (address) равен 24, а не 22, как можно было ожидать.

Заметьте, что имя типа становится доступным сразу после того, как оно встретилось, а не только после того, как полностью просмотрено все описание. Например:

struct link{ link* previous; link* successor; }

Новые объекты структурного типа не могут быть описываться, пока все описание не просмотрено, поэтому

struct no_good { no_good member; };

является ошибочным (компилятор не может установить размер no_good). Чтобы дать возможность двум (или более) структурным типам ссылаться друг на друга, можно просто описать имя как имя структурного типа. Например:

struct list; // должна быть определена позднее

struct link { link* pre; link* suc; link* member_of; };

struct list { link* head; }

Без первого описания list описание link вызвало бы к синтаксическую ошибку.


Содержание раздела