Использование конструктора в C ++ - PullRequest
12 голосов
/ 04 июля 2011

Это очень тривиальный вопрос относительно использования конструктора в C ++.Я буду представлять в форме диалога интервью (было трудно представить его в любых других формах)

интервьюер - что такое конструктор?
я - *Конструктор 1007 * - это специальные функции, которые обеспечивают инициализацию всех объектов перед их использованием.

интервьюер - что такое список инициализаторов?
me - это список, в котором происходит вся инициализация.Тело конструктора вводится только после инициализации всех элементов данных или вызова какого-либо конструктора всех объектов-членов.

интервьюер - , что означает, что инициализация выполняется в списке инициализаторов, а невнутри конструктора.Но вы сказали, что конструктор инициализирует объект!Не так ли?Вы хотите ответить на мой первый вопрос?
me - Я думаю, что конструктор выполняет присваивание, он вызывает оператор присваивания для уже инициализированных объектов-членов.

Так что мой вопрос к вам может быть

как работает список инициализаторов ?

что находится между начальным адресом функции и начальными скобками [{]?

или просто ответьтемне, как убедить моего интервьюера.

Ответы [ 5 ]

7 голосов
/ 04 июля 2011

Технически, ваша интерпретация точна. Никакие члены не могут быть инициализированы изнутри тела ctor; только в ctor-initializer. Любой членский доступ в теле ctor может быть только назначением.

Все члены "инициализируются" перед вводом тела ctor.

Однако, говоря более широко, поскольку тело всегда следует за инициализатором, говорят, что & mdash; как единое целое & ndash; объект инициализируется после завершения конструктора ... включая тело.

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

3 голосов
/ 04 июля 2011

Вы переосмысливаете это и позволяете интервьюеру сбить вас с толку.

Инициализация членов объекта не - это то же самое, что инициализация самого объекта . То, что члены имеют вменяемые значения, не означает, что объект был создан. Пока конструктор не завершится, сам объект не был должным образом инициализирован.

1 голос
/ 05 июля 2011

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

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

int var1; // declares/defines var of type int

int var2 = 0; // declares/defines a var of type int and initializes it to 0

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

int x = 5;
int y = 5;

int main()
{
    int x = x; // x is undefined here not 5 because x refers to itself
    int y[y];
    int size = sizeof(y)/sizeof(int); // size is 5 (y[5]) since y isn't defined until after the enclosing bracket so y referred to the global y in the declaration.
}

Существуют некоторые переменные, которые должны быть инициализированы, однако, .Константы и ссылки.

То же самое с конструкторами.Точка, в которой были определены члены, находится прямо перед телом ctor.Это порядок, в котором члены и базы определяются при вызове конструктора.

  1. виртуальные базовые классы
  2. базовый класс
  3. члены - впорядок, в котором они были объявлены
  4. выполняется тело ctor

После выхода из тела конструктора все было инициализировано.

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

1 голос
/ 04 июля 2011

Основными элементами списка инициализации являются эффективность и удобочитаемость кода.

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

например, вот пример списка инициализации, который я использовал в реализации двусвязного списка:

template <typename T>
LinkedList<T>::LinkedList()
: size(0)
, pHead(NULL)
, pTail(NULL)
{
}

В то время как менее эффективная версия, в которой размер, pHead и pTail назначаются дважды, показана ниже:

template <typename T>
LinkedList<T>::LinkedList()
{
    size = 0;
    pHead = NULL;
    pTail = NULL;
}
0 голосов
/ 04 июля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...