Почему мы не можем инициализировать элементы внутри структуры?

Почему мы не можем инициализировать элементы внутри структуры?

пример:

struct s {
   int i = 10;
};

person Santhosh    schedule 22.10.2008    source источник
comment
Потому что это определение, а не декларация   -  person Archmede    schedule 02.05.2017


Ответы (6)


Если вы хотите инициализировать нестатические элементы в struct объявлении:

В C++ (не C) structs почти синонимичны классам и могут иметь элементы, инициализированные в конструкторе.

struct s {
    int i;

    s(): i(10)
    {
    }
};

Если вы хотите инициализировать экземпляр:

In C or C++:

struct s {
    int i;
};

...

struct s s_instance = { 10 };

C99 также имеет функцию, называемую назначенными инициализаторами:

struct s {
    int i;
};

...

struct s s_instance = {
    .i = 10,
};

Существует также расширение GNU C, очень похожее на назначенные инициализаторы C99, но лучше использовать что-то более переносимое:

struct s s_instance = {
    i: 10,
};
person Alex B    schedule 22.10.2008
comment
Не могли бы вы уточнить свой самый последний пример? - person phougatv; 03.02.2016

Прямой ответ заключается в том, что определение структуры объявляет тип, а не переменную, которую можно инициализировать. Ваш пример:

struct s { int i=10; };

Это не объявляет никакой переменной — она определяет тип. Чтобы объявить переменную, вы должны добавить имя между } и ;, а затем инициализировать ее впоследствии:

struct s { int i; } t = { 10 };

Как отметил Чекерс, в C99 вы также можете использовать назначенные инициализаторы (что является замечательным улучшением — однажды C догонит другие функции, которые были в Fortran 66 для инициализации данных, в первую очередь повторение инициализаторов заданное количество раз). В этой простой структуре нет никакой выгоды. Если у вас есть структура, скажем, с 20 элементами и вам нужно инициализировать только один из них (скажем, потому что у вас есть флаг, который указывает, что остальная часть структуры инициализирована или нет), это более полезно:

struct s { int i; } t = { .i = 10 };

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

person Jonathan Leffler    schedule 22.10.2008

Обратите внимание, что в C++ 11 теперь разрешено следующее объявление:

struct s {
   int i = 10;
};

Это старый вопрос, но он занимает высокое место в Google и может быть прояснен.

person Turtlesoft    schedule 31.05.2016
comment
Что именно он делает? Сопоставимо ли это со значением инициализации конструктора по умолчанию? Если да: будет ли это назначение также выполняться, если вызывается конструктор копирования или перемещения? - person starturtle; 01.08.2016
comment
Он в основном вставляется в список инициализации членов ваших конструкторов, если член не инициализирован явно. - person Trass3r; 18.09.2017
comment
Это где-нибудь задокументировано? - person Andrew Truckle; 02.07.2018

Edit2: этот ответ был написан в 2008 году и относится к C++98. Правила инициализации членов изменились в последующих версиях языка.

Редактировать: вопрос изначально был помечен c++, но автор сообщения сказал, что он касается c, поэтому я повторно пометил вопрос, но я оставляю ответ...

В C++ struct — это просто class, который по умолчанию используется для public, а не private для членов и наследования.

C++ позволяет инициализировать встроенные элементы только static const, другие члены должны быть инициализированы в конструкторе или, если struct является POD в списке инициализации (при объявлении переменной).

struct bad {
    static int answer = 42; // Error! not const
    const char* question = "what is life?"; // Error! not const or integral
};

struct good {
    static const int answer = 42; // OK
    const char* question;
    good() 
        : question("what is life?") // initialization list
        { }
};

struct pod { // plain old data
    int answer;
    const char* question;
};
pod p = { 42, "what is life?" };
person Motti    schedule 22.10.2008
comment
Это довольно устарело... Теперь C++ это позволяет! - person sergiol; 15.05.2020

Мы не можем инициализировать, потому что, когда мы объявляем какую-либо структуру, а не то, что мы на самом деле делаем, просто сообщаем компилятору об их наличии, то есть для этого не выделена память, и если мы инициализируем член без памяти для этого. Обычно то, что происходит, когда мы инициализируем любую переменную, зависит от места, где мы объявили переменную, и компилятор выделяет память для этой переменной.

int a = 10;
  • если это авто, то в стеке память будет выделяться
  • если он глобальный, то в разделах данных память будет выделяться

Итак, какая память требуется для хранения этих данных, но в случае структуры памяти нет, поэтому ее невозможно инициализировать.

person Anup Raj Dubey    schedule 14.03.2016
comment
Хотя ваш ответ кажется хорошим, вы должны попытаться сделать его более ясным, например, исправив свои формулировки! - person gsamaras; 14.03.2016

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

person Ajay Sivan    schedule 31.05.2016