2013-03-22 6 views
1

Я читаю «Ускоренный C++» Эндрю Кенига и Барбары Э. Му, и я нахожусь в главе о конструкторах (5.1).Инициализация конструктора

Они упоминают здесь

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

Хотя мы явно инициализировали только midterm и final, другие элементы данных инициализируются неявно. В частности, n инициализируется конструктором по умолчанию string, а homework инициализируется конструктором по умолчанию vector.

Класс они говорят о том,

class Student_info { 
public: 
    std::string name() const (return n;} 
    bool valid() const {return !homework.empty();} 
    std::istream& read(std::istream&); 

    double grade() const; 
private: 
    std::string n; 
    double midterm, final; 
    std::vector<double> homework; 
}; 

и их конструктор по умолчанию является

Student_info::Student_info(): midterm(0), final(0) {} 

Я просто хотел бы уточнить, что это означает, что такие вещи, как int и double где ISN 't a std:: до того, как этот термин нужно будет инициализировать конкретно?

+0

«должен быть инициализирован _specifically_» - Вы можете фактически уехать из значения _specific_, и они все равно будут инициализированы все такие основные типы имеют нулевое значение. ': midterm()' будет устанавливать член '0.0', потому что это нулевое значение для' double'. Точно так же, если вы введете член 'int' в список инициализаторов, но не получите начального значения, он будет инициализирован' 0'. – MSalters

ответ

3

Это правильно.
Но std :: это не то, что вы ищете.

Любой из основных типов не инициализируется, если вы не сделаете это явно.

Так char/int/float/pointers и т. Д. Также (как указано в Ian ниже) любой класс/союзы без явного конструктора по умолчанию инициализируют его члены (что означает фундаментальное (и рекурсивно для членов s класса/union без и явного конструктора), что они остаются неопределенными).

Примечание стороны:

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

спасибо, что помогает! – sccs

+0

Элемент class, struct или union без конструктора также не будет инициализировать какие-либо фундаментальные типы, которые он содержит. –

+0

@ IanM_Matrix1: Вы абсолютно правы (предполагая по умолчанию, а не нулевую инициализацию). –

2

и double - это встроенные типы, а не классы, поэтому они не имеют конструкторов по умолчанию и по умолчанию не определены. Например:

int a; 
Student_info s; 

Синтаксис для обоих переменных одно и то же, но значение a не определено, в то время как значение s определено, потому что Student_info s фактически вызывает конструктор, т.е. Student_info s = Student_info();.

+0

'a' определено, но не инициализировано – pexeer

+0

Спасибо, я имел в виду, что значение' a' не определено. – valtron

1

Автор просто пытается показать конструктор по умолчанию, где все по умолчанию используется как эквивалент 0. Для строки и вектора они будут пусты. Для примитивных типов, таких как int и double, начальное значение этих примитивов во время объявления по умолчанию имеет значение, которое было в памяти, на которую указывает переменная. Это зависит от компилятора, хотя

+2

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

+0

ну, я думаю, мой профессор лгал мне тогда. Независимо от этого, это зависит от компилятора.Он может быть не определен для древних компиляторов C и C++, но тот, который я использовал до сих пор по умолчанию, равен 0 – Hien

+2

. Нет. Вы пропустили понимание того, что сказал ваш профессор (значение случайное и зависит от того, что является памятью и, следовательно, случайным). Но переменная находится в неопределенном состоянии. Стандарт говорит, что использование переменной в неопределенном состоянии является плохим. Вы видите 0, потому что вы компилируете в режиме отладки (который обычно инициализирует память, потому что это облегчает отладку). В режиме выпуска он не будет инициализировать память, если вы явно не сделаете это для дополнительной производительности. –

1

Это не относится к пространству имен std. n и домашнее задание являются классами, их конструктор будет вызываться во время построения Student_info. Но среднесрочные и конечные - это примитивные ценности, для них нет конструкторов. Инициализировать примитивный элемент в конструкторе необязательно, но хорошо.

0

Есть еще к этому.

1) Для примитивным или встроенных типов, неявно инициализации (или компилятор инициализирован) не означает, что не-оп (ничего не делает).

2) Для примитивным или встроенных типов, явно инициализируется (или инициализация программистом) очевидно :)

Как и в вашем примере:

Student_info::Student_info(): midterm(0), final(0) {} 

3) Для непримитивные типы, неявно инициализированы (или компилятор инициализирован) означает, что компилятор может (или не может) синтезировать конструктор с целью инициализации.

Usually, a constructor is synthesized by the compiler under the following cases: 

a) The non-primitive type is polymorphic or derives from some polymorphic/non-polymorphic types, 
b) The non-primitive type has a polymorphic/non-polymorphic member. 

Compiler synthesized constructor will usually have code to 

a) initialize v-pointer to v-table, 
b) call base class constructor, 
c) call constructors of members, so on, 

basically driven by the definition of non-primitive type. 

4) Для непримитивных типов, явно инициализации (или инициализируется пользователем прилагаемого конструктора) означает, что компилятор будет сделать вызов в определенный пользователем конструктор вместо того, чтобы синтезировать один для инициализации.

Например, вызывается конструктор по умолчанию, определенный соответствующими не-примитивными типами (например, std :: string или std :: vector).

**

Примечание: Компилятор все еще может увеличить код внутри пользовательского конструктора, чтобы сделать некоторые за кадром инициализации, как это будет необходимо (смотреть на шаг-3 выше для таких нужд) , Такой расширенный код всегда будет вставлен перед пользовательским кодом внутри конструктора!

**

+0

Почти (очень) хорошо, но вы являетесь беспорядочным построением по умолчанию («инициализировано компилятором») и генерацией компилятора def constr. Явная инициализация - вы explicitaly вызываете конструктор (независимо от того, что именно, может быть def constr, даже один, сгенерированный компилятором) и implicit или def const, компилятор вызывает def constr для вас, независимо от того, что он генерируется автоматически компилятором или определяемые пользователем. Конструктор по умолчанию простой, без аргумента. – qPCR4vir

+0

Вот краткий пример того, что я пытаюсь объяснить: http://stackoverflow.com/a/15416693/1458030 – qPCR4vir

+0

Извините, ваш комментарий немного запутан. msgstr "" "msgstr" "" msgstr "" "msgstr" "" msgstr "" "msgstr" "". Это становится очевидным, когда мы поставляем конструктор по умолчанию (тот, который не имеет никакого параметра). Компилятор обязан вызывать пользовательский конструктор по умолчанию всякий раз, когда происходит построение по умолчанию. – Arun

Смежные вопросы