Форум программистов, компьютерный форум CyberForum.ru

Какая разница в инициализации? - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 8, средняя оценка - 4.88
oxotnik
 Аватар для oxotnik
1584 / 1061 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
06.12.2011, 10:25     Какая разница в инициализации? #1
Есть класс:

C++
1
2
3
4
5
6
class CSomeClass
{
    CSomeClass();
private:
    bool isState1, isState2;
};
члены isState1, isState2 можно инициализировать 2-мя способами:
C++
1
2
3
4
5
// 1-й
CSomeClass::CSomeClass()
: isState1(true), isState2(false)
{
}
C++
1
2
3
4
5
6
//2-й
CSomeClass::CSomeClass()
{
    isState1 = true;
    isState2 = false;
}
Какая между ними разница? В смысле, в даном случае никакой не вижу, но если классы потом будут наследоваться, видоизменяться и т.д., то какой способ предпочтительней? Или при любом способе монопенисуально?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.12.2011, 10:25     Какая разница в инициализации?
Посмотрите здесь:

C++ Какая разница между cin и getline?
C++ [C++]Различные варианты инициализации указателя - в чём точная разница между ними?
C++ Какая разница?!
C++ какая разница между cin и scanf?
Какая разница? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
06.12.2011, 10:35     Какая разница в инициализации? #2
Цитата Сообщение от oxotnik Посмотреть сообщение
CSomeClass::CSomeClass()
: isState1(true), isState2(false)
Эта форма предназначена для вызова конструкторов предков isState1 и isState2, то есть isState1 и isState2 - классы-предки isState1. Соответственно удивляет тот компилятор, который проглотит эту форму при
Цитата Сообщение от oxotnik Посмотреть сообщение
class CSomeClass
, то есть без таких предков.
Цитата Сообщение от oxotnik Посмотреть сообщение
CSomeClass::CSomeClass()
{
isState1 = true;
isState2 = false;
}
В том случае, когда нет наследования, эта форма - единственная, иначе она не возможна, так как класс-потомок (в отличие от композита) просто не имеет членов с такими именами.
Bers
Заблокирован
06.12.2011, 10:41     Какая разница в инициализации? #3
1 случай: инициализация данных членов.

2 случай: инициализация данных членов дефолтными конструкторами, а потом присвоение им уже других значений.

В результате - падение производительности.

Если данные члены - тяжелые объекты, а скорость - критичный параметр, то падение производительности может оказаться существенным.

Если данные члены - примитивные типы данных, то возможно разницы не будит никакой (нужно смотреть ассм код)

Добавлено через 2 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
Эта форма предназначена для вызова конструкторов предков isState1 и isState2, то есть isState1 и isState2 - классы-предки isState1. Соответственно удивляет тот компилятор, который проглотит
ничего подобного:

C++
1
2
3
4
5
6
CScreenForm::CScreenForm(cSize_a x, cSize_a y, const char Char):
CColorTextForm(x,y,Char),  //конструктор папочки
myParent(NULL_PTR),          //данные-члены
myVisible(VISIBLE),            //данные-члены
myActive(ACTIVE_OBJ)       //данные-члены
{/*пуст за ненадобностью*/}
oxotnik
 Аватар для oxotnik
1584 / 1061 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
06.12.2011, 10:45  [ТС]     Какая разница в инициализации? #4
taras atavin, приведенный код абсолютно нормально компилится gcc, и в нем нет ничего зазорного ни с точки зрения логики ни с точки зрения стандарта.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
1 случай: инициализация данных членов. 2 случай: инициализация данных членов дефолтными конструкторами, а потом присвоение им уже других значений.
не совсем понял... оба случая - дефолтный конструктор (класса), разница только в способе (месте инициализации)
PointsEqual
ниначмуроФ
 Аватар для PointsEqual
832 / 516 / 33
Регистрация: 12.10.2009
Сообщений: 1,915
06.12.2011, 10:54     Какая разница в инициализации? #5
Цитата Сообщение от oxotnik Посмотреть сообщение
но если классы потом будут наследоваться, видоизменяться и т.д., то какой способ предпочтительней?
первый, тк
единственный способ вызвать конструкторы родительских классов с определёнными параметрами - список инициализации

Добавлено через 1 минуту
Цитата Сообщение от oxotnik Посмотреть сообщение
оба случая - дефолтный конструктор
во втором случае сначала вызывается конструктор по умолчанию, а затем только - оператор присваивания
Bers
Заблокирован
06.12.2011, 10:59     Какая разница в инициализации? #6
Цитата Сообщение от oxotnik Посмотреть сообщение
не совсем понял... оба случая - дефолтный конструктор (класса), разница только в способе (месте инициализации)
Проиллюстрируем на примере:
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
class Test
{
public:
    Test(): myVal(0){std::cout<<"Defolt\n";}
    Test(int val): myVal(val){ std::cout<<"Arg\n";}
    Test(const Test& rhs) { std::cout<<"Copy\n";}
 
    void operator=(int val) { myVal=val; std::cout<<"operator=\n"; }
private:
    int myVal;
};
 
class Agregat1
{
public: 
    Agregat1():myTest(333){}
    Test myTest;
};
 
class Agregat2
{
public: 
    Agregat2() {myTest = 333;}
    Test myTest;
};
 
 
int main()
{
    //HELLO;
 
    Agregat1 test1;
    
    std::cout<<"======\n";
    Agregat2 test2;
 
//вывод:
//Arg
//======
//Defolt
//operator
 
}
Таким образом во втором случае время тратится сначала на дефолтную инициализацию, а потом на присвоением с помощью operator=
oxotnik
 Аватар для oxotnik
1584 / 1061 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
06.12.2011, 10:59  [ТС]     Какая разница в инициализации? #7
Цитата Сообщение от PointsEqual Посмотреть сообщение
во втором случае сначала вызывается конструктор по умолчанию, а затем только - оператор присваивания
Имеется ввиду для членов isState...?
PointsEqual
ниначмуроФ
 Аватар для PointsEqual
832 / 516 / 33
Регистрация: 12.10.2009
Сообщений: 1,915
06.12.2011, 11:02     Какая разница в инициализации? #8
Цитата Сообщение от oxotnik Посмотреть сообщение
Имеется ввиду для членов isState...?
да, isState
Bers
Заблокирован
06.12.2011, 11:03     Какая разница в инициализации? #9
oxotnik, а есть ситуации, когда не получится просто так вызвать конструктор базового класса, даже если очень хочется, и остаётся лишь прибегать к услугам туловища конструктора потомка:
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
class Children;
class Parent
{
public:
 
    Parent():mPtr(NULL){} 
    Parent(Children& src):mPtr(&src){}
 
    void Init(Children& src) { mPtr=&src;}
 
    Children* mPtr;
};
 
class Children:public Parent
{
public:
    Children():Parent(*this) //выстрел в ногу! 
      //warning C4355: this: использован в списке
      // инициализации базового класса
    {  
        Init(*this);  //вот так правильно
    }
    
    Parent* mPtr;
};
KristopherRobin
 Аватар для KristopherRobin
137 / 133 / 6
Регистрация: 11.09.2011
Сообщений: 407
06.12.2011, 11:19     Какая разница в инициализации? #10
1й случай это типа инициализация конструктора в памяти заведутся переменные сразу со занчениями (true, false) после чего пойдет выполнение конструктора.

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

в книгах советуют первый способ т.к. он быстрее. а еще таким способом нужно вызывать конструкторы базового класса с аргументами.

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
class A
{
public: 
    A() {};
    A(int NewA); //как в унаследованных классах вызывать именно этот конструктор?
 
    int VarA;
};
 
class B: public A //наследуем класс А
{
public:
    B() {};
    B(int NewA, int NewB);
 
    int VarB;
};
 
A::A(int NewA):VarA(NewA)
{
}
 
B::B(int NewA, int NewB):A(NewA),VarB(NewB)  //вызов конструктора класса А с аргументом
{
 
}


C++
1
2
3
B::B(int NewA, int NewB):VarA(NewA),VarB(NewB) //попытка инициализоровать переменную базового класса без конструктора. переменная еще не появилась - не был вызван констурктор базового класса, а мы ее уже пытаемся инициализировать, поэтому вылезет ошибка
{
}

C++
1
2
3
4
5
B::B(int NewA, int NewB)  //вызовется конструктор базового класса A() без агрументов
{
    VarA = NewA; //И только после этого можно пристваить переменной значение
    VarB = NewB;
}
C++
1
2
3
4
B::B(int NewA, int NewB):A(NewA),VarB(NewB)  //вызов конструктора класса А с аргументом
{
                                                  //самый быстрый вариант
}
Bers
Заблокирован
06.12.2011, 11:22     Какая разница в инициализации? #11
Цитата Сообщение от KristopherRobin Посмотреть сообщение
после пойдет выполнение конструктора в котором им присвоятся значения (true, false)
Не правильно. Конструктор вызывается только один раз за время жизни объекта.
Для того, что бы изменить состояние объекта, будит вызван operator=
PointsEqual
ниначмуроФ
 Аватар для PointsEqual
832 / 516 / 33
Регистрация: 12.10.2009
Сообщений: 1,915
06.12.2011, 11:23     Какая разница в инициализации? #12
+ список инициализации - единственный способ инициализации константных членов и членов-ссылок класса

вроде преимуществ больше нет
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
06.12.2011, 11:25     Какая разница в инициализации? #13
А с какого предок вообще знает, что нужно потомку и как его инитить? Предок должен быть описан так, чтобы допускать отсутствие потомков с заранее заданными декларациями, твой инит - способ засунуть свою голову себе же в рот и подвесить кувалду возле челюсти. А если чилдрен не будет иметь определённого расширяющего члена? А ты в parent::init к нему уже обратился. А если потом ты решишь, что тот комплекс значений полей, которые parent::init в них запишет, не допустим? Но поведение parent::init уже стало частью реализации другого класса. А если ты потом закроешь расширяющий член? А parent::init уже к нему обращается. А если числдрен придётся переименовать? Но предку он уже известен под этим именем и под ним внесён в член предка.
oxotnik
 Аватар для oxotnik
1584 / 1061 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
06.12.2011, 11:26  [ТС]     Какая разница в инициализации? #14
Цитата Сообщение от PointsEqual Посмотреть сообщение
членов-ссылок класса
вот здесь поподробней, на примере... не представяю себе член-ссылку
Bers
Заблокирован
06.12.2011, 11:32     Какая разница в инициализации? #15
Цитата Сообщение от oxotnik Посмотреть сообщение
вот здесь поподробней, на примере... не представяю себе член-ссылку

C++
1
2
3
4
5
6
7
8
9
class Test
{
public:
    Test(int val): ref(val){}
    int& ref; //как известно, ссылка должна 
                //быть инициализирована явно
                //в другой момент времени
               // задать ей значение нельзя
};
oxotnik
 Аватар для oxotnik
1584 / 1061 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
06.12.2011, 11:38  [ТС]     Какая разница в инициализации? #16
Bers, не понимаю как этот пример использовать:
Код
class Test
{
public:
    Test(int val): ref(val){}
    int& ref;
};

int main()
{
    int i = 100;
    Test(i);
    return 0;
}
так не компилится
а так:
Код
int main()
{
    Test(100);
    return 0;
}
смысл ссылки теряется
Bers
Заблокирован
06.12.2011, 11:41     Какая разница в инициализации? #17
Цитата Сообщение от oxotnik Посмотреть сообщение
смысл ссылки теряется
да это просто пример, как можно инициализировать ссылку.
Ну можно так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Test
{
public:
    Test(int& val): ref(val){}
    int& ref; //как известно, ссылка должна быть инициализирована явно
    //в другой момент времени задать ей значение нельзя
};
 
int main()
{
    //HELLO;
 
    int a=10; //настоящий пассажир остался снаружи
    Test t(a); //а ссылка на него внутри объекта
    EndProgramm();
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.12.2011, 11:43     Какая разница в инициализации?
Еще ссылки по теме:

C++ Какая разница между двумя алгоритмами?
C++ Какая разница между аргументами и параметрами?
Какая разница что возвращать в main? C++

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

Или воспользуйтесь поиском по форуму:
oxotnik
06.12.2011, 11:43  [ТС]     Какая разница в инициализации?
  #18

Не по теме:

ой, блин, ступил немного

Yandex
Объявления
06.12.2011, 11:43     Какая разница в инициализации?
Ответ Создать тему
Опции темы

Текущее время: 05:55. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru