Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.95/103: Рейтинг темы: голосов - 103, средняя оценка - 4.95
1 / 1 / 0
Регистрация: 02.08.2012
Сообщений: 15
1

Отличие объявления, определения и инициализации

26.06.2013, 23:57. Показов 19127. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, товарищи.

Читаю тут книжицу по C++, учусь потихоньку.
И возник у меня вопрос нерядового характера: в чём фундаментальное отличие объявления, определения и инициализации? В книге всё намешано, ничего не понятненько.

Однако усёк, что они говаривают, будто такая строка:
C++
1
int a = 3;
не просто присваивание переменной значения, а что-то большее.
И как-то это связано с созданием экземпляров классов.

А ещё пишут, что есть инициализация прямая и инициализация копии.
А потом вот это кажут:
C++
1
2
int val = 1024;
int val (1024);
И говаривают, будто val в обоих случаях будет одинаковой.

Что-то я видно не секу истинной сути.
Помогите словцом мудрым.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.06.2013, 23:57
Ответы с готовыми решениями:

Правила объявления инициализации
Напишите основные - самые главные правила обьявления инициализации.

В чём отличие разных способов объявления переменных?
в чем отличие int a(2); от int a=2; И как писать правильней

Сложные определения и объявления
Решил создать отдельный топик т.к. ну совсем никак не могу разобраться (все взято с книги) есть...

Объявления и определения структур
Может кто-нибудь объяснить как это работает: //Source1.cpp #include "pch.h" #include...

42
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
27.06.2013, 13:14 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Croessmah Посмотреть сообщение
задание начального правильного значения, а это и есть инициализация
Тогда дейстие в коде (15 пост) можно назвать инициализацией (с применением механизма присваивания)?
Цитата Сообщение от Croessmah Посмотреть сообщение
но только различие в том, какой механизм используется - механизм инициализации или механизм присвоения
Отличие в том, что в механизме инициализации используются конструкторы?
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
27.06.2013, 13:50 22
@alsav22, Ну на счет механизмов это я просто так выразился, корректнее, наверное, сказать по другому:
C++
1
int a(1024);//инициализация
C++
1
2
int a;//создаем со значением по умолчанию (в данном случае с мусором)
a=1024;//не инициализация, а присвоение начального значения.
имхо, так будет правильнее
второй случай - инициализация с точки зрения определения инициализации и присвоение с точки зрения языка.
С классами же все совершенно очевидно, ибо при создании будет вызван конструктор, который и должен инициализировать объект, а при присвоении будет вызван оператор присвоения.
0
Почетный модератор
Эксперт С++
5850 / 2861 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
27.06.2013, 14:05 23
Я прошу прощения если не в тему, но нельзя ли перефразировать так:
C++
1
int a;//инициализация мусором
?

0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
27.06.2013, 14:10 24
@SatanaXIII, Как, правило, нельзя, ибо нет никакой инициализации - просто выделение места с тем значением, которое будет в памяти валяться то есть создание без задания какого-либо значения, имхо.
0
Почетный модератор
Эксперт С++
5850 / 2861 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
27.06.2013, 14:26 25
Цитата Сообщение от Croessmah Посмотреть сообщение
то есть создание без задания какого-либо значения, имхо.
то есть создание без задания какого-либо конкретного значения
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
27.06.2013, 14:45 26
Цитата Сообщение от SatanaXIII Посмотреть сообщение
int a;//инициализация мусором
Это не всегда верно.
Для объектов со статическим временем жизни (static storage duration)
выполняется так называемая инициализация нулем (zero-initialization).
C++
1
2
3
4
5
6
7
8
int a; // Будет равно нулю.
 
int main()
{
    int b; // А вот здесь будет мусор.
 
    return 0;
}
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
27.06.2013, 14:51 27
Цитата Сообщение от Croessmah Посмотреть сообщение
С классами же все совершенно очевидно, ибо при создании будет вызван конструктор, который и должен инициализировать объект
Предположим, был вызван конструктор по умолчанию, который ничего не сделал и в полях объекта остался мусор. Объект всё равно считается инициализированным? Или нет? Почему тогда:
C++
1
int a; // неинициализированный объект
Ведь то же самое (может даже и конструктор по умолчанию вызывается).
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
27.06.2013, 14:57 28
@alsav22, Конструктор предназначен для инициализации объекта. Он вызван, значит объект можно назвать инициализированным, а то, что программист делает в конструкторе всем наплевать главное, чтобы порносайты при этом не открывались
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
27.06.2013, 14:58 29
Цитата Сообщение от Убежденный Посмотреть сообщение
int b; // А вот здесь будет мусор.
В общем случае, да. Но на старинном ваткоме в отладочном режиме инициализировалось нулями, насколько я помню. Да и https://ideone.com/uGgHt1 дает 0. Короче говоря, "мусорное" значение вполне детерминированно может быть нулём. Но безусловно это всё не регламентируется стандартом.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
27.06.2013, 15:26 30
Цитата Сообщение от Tulosba Посмотреть сообщение
Но безусловно это всё не регламентируется стандартом.
Если быть совсем дотошным, то вот:
C++ 2003

8.5 Initializers

...

6. Every object of static storage duration shall be zero-initialized at program
startup before any other initialization takes place.

...

9. If no initializer is specified for an object, and the object is of (possibly cv-qualified)
non-POD class type (or array thereof), the object shall be default-initialized; if the
object is of const-qualified type, the underlying class type shall have a user-declared
default constructor. Otherwise, if no initializer is specified for a non-static
object, the object and its subobjects, if any, have an indeterminate initial value
.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
27.06.2013, 15:54 31
Если вспомнить книгу Макконнелла, то если переменной при создании не задается значение и она содержит мусор, то это неверная инициализация
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
27.06.2013, 16:23 32
Цитата Сообщение от Croessmah Посмотреть сообщение
неверная инициализация
Неверных инициализаций не бывает. То есть взаимно это как-то.
Вообще, для новичка такие вещи как объявление, определение и инициализация, - предварительное объявление, как и многое другое. Нельзя язык учить как букварь, многое можно понять значительно позже ознакомления.
@_Cherep_, объявление это информация для компилятора для формирования кода. С местом объявления связаны: время жизни, видимости, действия переменной, например.
Определение - информация компилятору и редактору связей для конкретизации значения или адреса.
Инициализация - совмещение, того и другого. Тема большая. Вам пока достаточно понять, что константы и ссылки, невозможно объявить без инициализации. А уж как работают конструктора при инициализации или присваивании это лучше читать и спрашивать конкретно.
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,644
Записей в блоге: 13
27.06.2013, 16:47 33
В C++ есть такие понятия:

1) объявление (декларация)
2) определение (дефиниция)

Пояснить что есть что, проще всего на примере функций:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
int F1(int a);
{
    int i,j;
    ...
    j=F2(i);
 
    return ...
}
 
int F2 (int x)
{
 ...
}

Этот код не скомпилируется, т.к. в момент компиляции F1 компилятор ничего не знает про F2.
Чтобы код скомпилировался, функцию F2 нужно предварительно объявить (декларировать):

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int F2(int);  // Декларация F2
 
int F1(int a);
{
    int i,j;
    ...
    j=F2(i);
 
    return ...
}
 
int F2 (int x)  // Дефиниция F2 (определение)
{
 ...
}
Другой вариант: разместить определение F2 перед F1:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
int F2 (int x)  // Дефиниция F2 (определение)
{
 ...
}
 
int F1(int a);
{
    int i,j;
    ...
    j=F2(i);
 
    return ...
}
Теперь декларация не нужна (поскольку всякая дефиниция является одновременно и декларацией).

Ну, а инициализация - это присвоение объекту или переменной некоего значения в момент создания.
1
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
27.06.2013, 16:47 34
@IGPIGP, Откопал у Макконнелла
Неверная инициализация данных - один из плодородных источников ошибок в программировании. Эффективные способы предотвращения проблем с инициализацией могут значительно ускорить отладку.
При неверной инициализации проблемы объясняются тем, что переменная имеет не то первоначальное значение, которое вы ожидаете. Это может случиться по одной из следующих причин.
- Переменной не было присвоено значения. Она имеет то случайное значение, которое находилось в соответствующих ячейках памяти при запуске программы.
- Значение переменной устарело. Когда-то переменной было присвоено значение, но оно утратило свою актуальность.
- Одним частям переменной были присвоены значения, а другим нет.
1
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
27.06.2013, 17:43 35
Цитата Сообщение от Croessmah Посмотреть сообщение
Неверная инициализация данных - один из плодородных источников ошибок в программировании.
Это правда. Тем не менее может же быть случай когда переменная должна быть объявлена и не может быть проинициализирована полностью. Например если классы связны указателями друг на друга.
Новичку это ненужно. :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <string>
#include <typeinfo.h>
using namespace std;
class A {
int a;
double b;
string c;
public:
    A()
        :a(1), b(2.0), c("a anb b were sitting on a pipe")  
    {}
A(int a_)//частично инициализирует
:a(a_)
{}
A(double b_)//частично инициализирует
:b(b_)
{}
A(string c_)//частично инициализирует
:c(c_)
{}
A(const A& orig)//копирующий (и полностью инициализирующий)
:a(orig.a), b(orig.b), c(orig.c)
{}
    int& propertyA(){
return a;
}
    double& propertyB(){
return b;
}
string& propertyC(){
return c;
}
};
int main()
 {
     A *b=new A;//динамическая память выделена но не инициализирована
     cout<<b->propertyA()<<endl;//мусор если конструктор по умолчанию (без параметров) закоментирован
 
     A a;//память на стеке выделена
     cout<<a.propertyA()<<endl;////мусор если конструктор закоментирован
     a.propertyA()=2;// заполняется простым присваиванием
     a.propertyB()=5.0;// заполняется простым присваиванием
     a.propertyC()="a+b= ";// заполняется простым присваиванием
     
     cout<<a.propertyA()<<endl;
     cout<<a.propertyB()<<endl;
     cout<<a.propertyC()<<a.propertyA()+a.propertyB()<<endl;
 
     A c(a);//A c = a; - аналогично, полноценность инициализации определяется полноценность конструктора копии
 
     cout<<c.propertyA()<<endl;
     cout<<c.propertyB()<<endl;
     cout<<c.propertyC()<<a.propertyA()+a.propertyB()<<endl;
 
     A d = "Oi scolco musora budet esli razremite stroki nige...";//работает конструктор преобразования принимающий строку
     //остальные поля не инициализированы
     //отложенную, частичную инициализацию можно использовать для связывания двух экземпляров классов, когда
     //один из них обявлен опережающим объявлением, но не может быть полностью инициализирован без указателя на
     //второй, а второму для создания экземпляра нужен указатель на первый
     //такую штуку (создание пары связянных объектов разных классов можно описать в глобальном или статическом методе
     //или написать для этого отдельный класс.
     cout<<d.propertyC()<<endl;
     //cout<<d.propertyA()<<endl;
     //cout<<d.propertyB()<<endl;
     system("pause");
     }
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
27.06.2013, 17:49 36
Цитата Сообщение от IGPIGP Посмотреть сообщение
Например если классы связны указателями друг на друга.
В таком случае следует инициализировать неким нулевым значением, которое будет четко говорить, что поле не инициализировано. А не оставлять его в "мусорном" состоянии. Например должно быть как минимум так:
C++
1
2
3
A(int a_)//частично инициализирует
:a(a_), b(0) // c - не нужно, т.к. std::string инициализируется конструктором по умолчанию
{}
1
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
27.06.2013, 17:55 37
Не нужно новичку?
Да ТС, наверное, уже в шоке от всей нашей писанины
1
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
27.06.2013, 18:01 38
Цитата Сообщение от Tulosba Посмотреть сообщение
В таком случае следует инициализировать неким нулевым значением,
Может и правда. А если, ход выполнения одного из методов инициализации зависим от значения поля? Или поле - файловый поток, например?
Конечно если слить такие классы в один, то такой вопрос обходится, а если не нет? У меня маловато опыта, чтобы сказать определённо.

Добавлено через 4 минуты
Цитата Сообщение от Croessmah Посмотреть сообщение
Да ТС, наверное, уже в шоке от всей нашей писанины
Не может быть. Сейчас заметил: в заголовке typeinfo,h забыл удалить и вообще сырой кусок.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
27.06.2013, 18:03 39
Цитата Сообщение от IGPIGP Посмотреть сообщение
А если, ход выполнения одного из методов инициализации зависим от значения поля?
Ради бога. Пусть зависит. Главное чтобы объект был в согласованном состоянии, т.е. сохранятся инвариант класса.
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
27.06.2013, 18:39 40
Цитата Сообщение от Tulosba Посмотреть сообщение
Главное чтобы объект был в согласованном состоянии, т.е. сохранятся инвариант класса.
Это безопаснее конечно, но немного дольше. Разве нет?
0
27.06.2013, 18:39
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.06.2013, 18:39
Помогаю со студенческими работами здесь

Циклы for. Проблема объявления/инициализации
Эх, так и придется создавать новую тему. А то, блин, интересно ж... Итак, я тут в недавней теме...

Написать программу объявления, создания и инициализации двумерного прямоугольного массива
Написать программу объявления, создания и инициализации (при объявлении) двумерного...

Когда выделяется память под переменные - во время объявления или инициализации
Привет! Вопрос такой: когда выделяется память под переменные - во время объявления или...

Архитектура правильного определения и объявления класса
Всем привет! В процессе написания одной программы &quot;поймал&quot; себя на том, что видимо не до конца...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru