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

Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 117, средняя оценка - 4.91
RASHFor
6 / 6 / 0
Регистрация: 12.02.2012
Сообщений: 224
09.09.2012, 20:23     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #1
1)Любезные,скажите когда надо исп. списки инициализации, а когда можно заменить констуктором по умолчанию?
2) правильно ли утверждение,что списки инициализации можно заменить к.по умолчанию?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.09.2012, 20:23     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию?
Посмотрите здесь:

Перестало выводить, когда задание списков перевел в конструкторы, когда были просто функции выводило нормально. C++
Когда создается конструктор по умолчанию? C++
C++ Когда какой контейнер использовать?
Записать условия когда является истинным , когда: C++
C++ Когда используется * перед указателями, а когда нет?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
09.09.2012, 20:32     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #2
Уточните-ка, какие именно списки инициализации вы имеете ввиду? Списки инициализации объектов? Или список инициализации конструктора?
RASHFor
6 / 6 / 0
Регистрация: 12.02.2012
Сообщений: 224
09.09.2012, 20:43  [ТС]     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #3
э..Наверное списки инициализации объектов...
Вот это я имею в виду:
C++
1
2
3
4
5
6
7
8
9
10
11
class Foo
{
public:
    Foo(int i, int j = 0)
        :m_i(i)
        ,m_j(j)
    {
    }
private:
    int m_i, m_j;
};
Ну а списки инициализации конструкторов, это же тоже самое в принципе?
2)Вот инициализация конструктора,да ?:
C++
1
2
3
4
5
6
7
8
9
10
class MyFile
{
public:
    MyFile():m_pFile(NULL)
    {}
 
    ~MyFile()
    {
        Close();
    }
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
09.09.2012, 20:51     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #4
Нет, всё это списки инициализации конструкторов. Список инициализации объекта вот, например:
C++
1
2
3
4
5
6
7
8
9
10
struct Object
{
    int a;
    double b;
    char c;
};
 
...
 
Object obj = {42, 3.14, 'x'};
Ну а теперь ответьте на вопрос: как можно список инициализации заменить конструктором по умолчанию? И как можно воду заменить жареной картошкой? Это я к тому, что вещи это разные. Либо я не понял вопроса. Попробуйте пояснить, что вы подразумеваете под подобной заменой?
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6168 / 2897 / 282
Регистрация: 04.12.2011
Сообщений: 7,704
Записей в блоге: 3
09.09.2012, 20:57     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #5
Цитата Сообщение от RASHFor Посмотреть сообщение
1)Любезные,скажите когда надо исп. списки инициализации, а когда можно заменить констуктором по умолчанию?
2) правильно ли утверждение,что списки инициализации можно заменить к.по умолчанию?
Список инициализации, например, - единственный выход для инициализации не статических констант класса. Их можно объявить, в теле объявления (сигнатуре) класса, а определить в конструкторе, применив инициализацию списком.
зы для случая приведенного Вами, можно легко провести инициализацию в теле конструктора присвоением. И компилятор это примет. Тут нет разницы. А вот константу так инициализировать не даст.)
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
09.09.2012, 21:03     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #6
IGPIGP, да банальнейший пример - вызов конкретного конструктора базового класса можно сделать только в списке инициализации.
RASHFor
6 / 6 / 0
Регистрация: 12.02.2012
Сообщений: 224
09.09.2012, 21:09  [ТС]     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #7
Спасибо.И всё же.))
C++
1
2
3
4
5
6
7
8
9
10
11
class Foo
{
public:
    Foo(int i, int j = 0)//Это конструктор?(и почему int j = 0 ,а int i только объявленно и не присвоенно значение? )
        :m_i(i)//это список инициализации?
        ,m_j(j)
    {
    }
private:
    int m_i, m_j;
};
П.С Вопросы скорей всего тупые и вас бесят,но я так быстрее пойму,если буду знать ответы.Спс,за терпение.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
09.09.2012, 21:14     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #8
RASHFor, да, это конструктор. С двумя параметрами. Один из них (второй) имеет значение по умолчанию. Это значит, что конструктор может быть вызван как с одним, так и с двумя аргументами. В первом случае вызов Foo bar(10) эквивалентен вызову Foo bar(10, 0) (если второй аргумент явно не указан, будет передано его значение по умолчанию). После двоеточия через запятую идёт список инициализации конструктора, по факт - вызов конструкторов других объектов.
RASHFor
6 / 6 / 0
Регистрация: 12.02.2012
Сообщений: 224
09.09.2012, 21:18  [ТС]     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #9
Спасибо,вроде въехал.трошки.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
09.09.2012, 21:34     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #10
Тут почитайте: Двоеточие в конструкторе
Явное наследование конструкторов
schoolboy_
1 / 1 / 0
Регистрация: 02.03.2013
Сообщений: 59
31.01.2015, 21:06     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #11
Как, используя список инициализации, организовать проверку передаваемых в конструкторе значений?
Скажем, если значение больше нуля, то этим значением инициализируем поле класса, иначе нет.
C++
1
2
3
4
5
6
7
8
9
10
11
class Foo
{
public:
    Foo(int i, int j = 0)//Это конструктор?(и почему int j = 0 ,а int i только объявленно и не присвоенно значение? )
        :m_i(i)//это список инициализации?
        ,m_j(j)
    {
    }
private:
    int m_i, m_j;
};
hoggy
5225 / 2116 / 403
Регистрация: 15.11.2014
Сообщений: 4,800
Завершенные тесты: 1
31.01.2015, 21:31     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #12
Цитата Сообщение от IGPIGP Посмотреть сообщение
писок инициализации, например, - единственный выход для инициализации не статических констант класса.
неужели?

http://rextester.com/RLMP92136

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Title of this code
//g++  4.8.2
 
#include <iostream>
 
 
struct example
{
    void view()const { std::cout<<"value = "<< value<<'\n'; }
    const int value = 10;
    
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    example().view();
}
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6168 / 2897 / 282
Регистрация: 04.12.2011
Сообщений: 7,704
Записей в блоге: 3
31.01.2015, 21:53     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #13
Цитата Сообщение от hoggy Посмотреть сообщение
неужели?
hoggy, больше года как это обсуждалось.
Константа встроенного типа с инициализирующим значением не передаваемым в конструктор становится угрожающе статической. Ведь инициализируя её литералом или другой константой Вы делаете её одинаковой для всех экземпляров. Хотя каждый будет иметь свою копию в отличие от настоящей статической константы. Я затрудняюсь определить пол такой переменной. Но может где-то и нужно такое. Расскажите где.
Я не имею большого опыта и хотел сказать о, примерно, таком случае:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
class NoStaticConst{
public:
NoStaticConst(int);
const int a;
};
NoStaticConst::NoStaticConst(int a_)
:a(a_)//ok однако закомментируйте эту строку и раскомментируйте ту что сейчас закомментирована ниже
{
//a=a_; //не получится
}
int main()
{
NoStaticConst a(5);
cout<<a.a<<endl;
system("pause");
    return 0;
}
hoggy
5225 / 2116 / 403
Регистрация: 15.11.2014
Сообщений: 4,800
Завершенные тесты: 1
31.01.2015, 22:03     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #14
Цитата Сообщение от IGPIGP Посмотреть сообщение
Константа встроенного типа с инициализирующим значением не передаваемым в конструктор становится угрожающе статической.
"угрожающе статической" - это что, определение гуманитариев?

Она была и остается обычным мембером класса.

Причем, совершенно не принципиально встроенный это тип, или нет:

http://rextester.com/TNHWV64207

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Title of this code
//g++  4.8.2
 
#include <iostream>
#include <functional>
 
 
struct example
{
    typedef std::function<void()>
        delegate;
    
    void view()const { std::cout<<"value = "<< value<<'\n'; }
    const int value = 10;
    
    const delegate hello = [](){ std::cout<<"Hello, world!\n";  };
};
 
int main()
{
    example().hello();
}
На самом деле все гораздо проще:
мемберы можно инициализировать не только в списках инициализации.

Вот и все.


Цитата Сообщение от IGPIGP Посмотреть сообщение
:a(a_)//ok однако закомментируйте эту строку и раскомментируйте ту что сейчас закомментирована ниже
{
//a=a_; //не получится
}
Ваше "не получится" - это присвоение, а не инициализация.

Очевидно, что раз мембер - константа, то присвоить ему новое значение уже нельзя.
Только к инициализации это вообще не имеет никакого отношения
schoolboy_
1 / 1 / 0
Регистрация: 02.03.2013
Сообщений: 59
31.01.2015, 22:05     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #15
hoggy, ответте на мой вопрос, пожалуйста. Похоже, в данной ветке вы самый "прошаренный"
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6168 / 2897 / 282
Регистрация: 04.12.2011
Сообщений: 7,704
Записей в блоге: 3
31.01.2015, 22:10     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #16
Цитата Сообщение от hoggy Посмотреть сообщение
Ваше "не получится" - это присвоение, а не инициализация.
Холливар? Не интересует.
Цитата Сообщение от hoggy Посмотреть сообщение
Она была и остается обычным мембером класса.
А кто спорит. Но увсех мемберов этого пола:
const int a = 10;
для всех экземпляров будет одно значение: 10
А присвоение при объявлении и в теле конструктора это инициализация. Хотя синтаксически - присвоение.

Не по теме:

В чём источник энергии спора? Любовь к истине?

hoggy
5225 / 2116 / 403
Регистрация: 15.11.2014
Сообщений: 4,800
Завершенные тесты: 1
31.01.2015, 23:12     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #17
Цитата Сообщение от RASHFor Посмотреть сообщение
1)Любезные,скажите когда надо исп. списки инициализации, а когда можно заменить констуктором по умолчанию?
Область применения списка инициализации:
когда возникла необходимость определить конструктор.



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

Цитата Сообщение от RASHFor Посмотреть сообщение
2) правильно ли утверждение,что списки инициализации можно заменить к.по умолчанию?
Вопрос звучит примерно так:
"правильно ли утверждение, что колесо автомобиля можно заменить автомобилем?"

Добавлено через 10 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Холливар?
Правила языка с++

Цитата Сообщение от IGPIGP Посмотреть сообщение
const int a = 10;
для всех экземпляров будет одно значение: 10
Ну и что? Смысли к чему это было сказано?

Цитата Сообщение от IGPIGP Посмотреть сообщение
А присвоение при объявлении и в теле конструктора это инициализация. Хотя синтаксически - присвоение.
Во-первых, в теле конструктора нет никаких объявлений мемберов.
Мемберы объявляются в декларации класса.

А во-вторых:

http://rextester.com/OHL21223


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
//Title of this code
//g++  4.8.2
 
#include <iostream>
 
 
struct value
{
    value()
        :v(0)
    { 
        std::cout<<"value: я был создан и проинициализирован нулем\n"; 
    }
    
 
    value& operator=(int a) 
    {
        std::cout<<"value: изменяю значение на новое: "<< a<<'\n';
        v = a;
        return *this;
    }
    
    int v;
             
             
};
 
 
struct example
{
    example()
        :v()
    {
        std::cout<<"example: запустился мой конструктор\n";
        v = 100;    
    }
    value v;
};
 
int main()
{
    example();
}
Называть инициализацией то, что не имеет к ней ни малейшего отношения - это либо неопытность, и тогда это пройдет.
Либо глупость. А это уже не лечится.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Но может где-то и нужно такое. Расскажите где.
В общем случае это может быть нужно тогда,
когда требуется гарантировать неизменность данных.

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

Например, мне попадалась задача, где были ноды, которые по задаче не могли существовать без родителя,
и не могли его поменять на протяжении своей жизни.
А самого родителя могли использовать только для чтения.
Но не для изменения.
И поэтому, я использовал const reference.
-------------------------------------------------------------------

Ещё бывают случаи, когда есть внешние статические неизменяемые данные.
А конкретные объекты-потребители в целях оптимизации держат на них лишь ссылки/указатели.

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

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

В коде это могло бы выглядеть примерно так:

http://rextester.com/HUAX7966

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
//Title of this code
//g++  4.8.2
 
#include <iostream>
 
struct simulator //<--- предположим это некий механизм симуляции чего-то
{
    const int param; //<--- отвечает за какой то важный параметр симуляции
          //он константен, поскольку разработчики сочли важным свойством: 
          //он ни при каких обстоятельствах не должен измениться
    
    const char* name; //<--- имя никогда 
         //ни при каких обстоятельствах не должно измениться
    
    template<class T>
    simulator(const T& programm) //<--- механизм получает неккую "программу симуляции"
        :param(T::ID)              // которую и должен отыгрывать.
        ,name(T::getName())
    {
        std::cout<<"симулятор: загрузка программы завершена\n";
            std::cout<<"симулятор: программа: '" << name<<"'\n";
        std::cout<<"симулятор: идентификационный номер: " << param<<'\n';
        
    }
    
    void work()const
    {
        std::cout<<"симулятор: запускаю симуляцию ... '"<<name<<"'\n";
    }
};
 
struct live
{
    enum { ID = 1 };
    static const char* getName() { return "жизнь"; }
};
 
struct virus
{
    enum { ID = 2 };
    static const char* getName() { return "вирус"; }
};
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    simulator( live() ).work();
    std::cout << "-----------------------------\n";
    simulator( virus() ).work();
}
Обратите внимание:
разные экземпляры класса simulator используют разные источники данных для name.

Но изменять содержимое объекта на который указывает name нельзя ни при каких обстоятельствах.
Потому что изменение объектов являющихся константами от рождения - есть UB.

Автор кода помечает name квалификатором const, что бы гарантировать это положение.
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6168 / 2897 / 282
Регистрация: 04.12.2011
Сообщений: 7,704
Записей в блоге: 3
01.02.2015, 00:49     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #18
Цитата Сообщение от hoggy Посмотреть сообщение
В общем случае это может быть нужно тогда,
когда требуется гарантировать неизменность данных.
Вы говорите о необходимости статических констант? А я спросил о том, зачем может понадобиться куча одинаковых по значению копий (мемберов как вы говорите).
Фраза:
Цитата Сообщение от IGPIGP Посмотреть сообщение
каждый будет иметь свою копию в отличие от настоящей статической константы.
в ней ясно, что речь не о статической константе, а о константе члене. И о бессмысленности её инициализации литералом, а не внешним параметром. Но Вы хотите не увидеть и пишете:
Цитата Сообщение от hoggy Посмотреть сообщение
Она была и остается обычным мембером класса.
Хотя нигде не говорилось иного.
Ещё фраза:
Цитата Сообщение от IGPIGP Посмотреть сообщение
А присвоение при объявлении и в теле конструктора это инициализация. Хотя синтаксически - присвоение.
Тут перечислены 2 случая, но не через запятую а с союзом "и":
a) int a = 123;//глобально, локально, как угодно
б) объявление в классе, а инициализация присвоением в конструкторе. Это вопрос скользкий и в общем случае наверное инициализации тут нет, а есть присваивание. Не буду спорить, - неточно сказал.
Но вопрос ТС:
Цитата Сообщение от RASHFor Посмотреть сообщение
а когда можно заменить конструктором по умолчанию?
оставляет только догадываться о чём он пытался спросить. Возможно о том, что когда в членах определены конструкторы преобразования и не определены конструкторы по умолчанию, то инициализация в списке, это способ гарантирующий инициализацию до вызова любого из методов. Однако, судя по тому как вопрос задан, это наверное и хорошо, что никто не стал об этом говорить. Надеюсь продолжения не будет.
Shaman1387
0 / 0 / 0
Регистрация: 24.01.2015
Сообщений: 6
01.02.2015, 01:39     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #19
Простое правило, которое использую лично я, если это конструктор в котором просто инициализируются данные, то - это список инициализации, если есть выделение памяти или же какие-то еще нюансы, тогда описываю все в конструкторе, а по-поводу консруктора по-умолчанию, его всегда надо писать по-умолчанию и через тот же список инициализации задавать значения по-умолчанию.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.02.2015, 01:41     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию?
Еще ссылки по теме:

Когда использовать WinAPI, а когда функции языка? C++
Когда стоит использовать класс, а когда лучше обойтись без них? C++
Объяснить (с примерами) для чего нужен RTTI, как и когда его можно и нужно использовать C++

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

Или воспользуйтесь поиском по форуму:
hoggy
5225 / 2116 / 403
Регистрация: 15.11.2014
Сообщений: 4,800
Завершенные тесты: 1
01.02.2015, 01:41     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию? #20
Цитата Сообщение от IGPIGP Посмотреть сообщение
Вы говорите о необходимости статических констант? А я спросил о том, зачем может понадобиться куча одинаковых по значению копий (мемберов как вы говорите).
Нет.

Если вы внимательно перечитаете, то увидете, что речь идет о не статических членах класса.

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

Цитата Сообщение от IGPIGP Посмотреть сообщение
о бессмысленности её инициализации литералом, а не внешним параметром.
Ложь. Изначальный тезис был:

Цитата Сообщение от IGPIGP Посмотреть сообщение
Ведь инициализируя её литералом или другой константой Вы делаете её одинаковой для всех экземпляров.
Я привел пример использования не статического,
и неизменяемого члена класса, который инициализируется другой константой.

Инициализация неизменяемого нестатического члена класса только литералами действительно избыточна,
и не эффективна, поскольку не имеет никаких полезных свойств,
которые нельзя было бы заполучить более эффективным способом:
при помощи локальных статических объектов.

Однако, класс не контролирует источник данных для своих конструкторов.
И не может накладывать на это никаких ограничений.

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

Может быть так:
C++
1
some obj("hello");
может быть так:

C++
1
2
3
static const char* data[] = { .... };
...
some obj(data[index] );
может быть так:

C++
1
some obj( other::class_name  );
или как то ещё.

А в отсутствии ограничений само по себе рассуждение на тему:
"бессмысленности инициализации литералом, а не внешним параметром" - не имеет смысла.

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

Цитата Сообщение от IGPIGP Посмотреть сообщение
Хотя нигде не говорилось иного.
Вы писали:
Цитата Сообщение от IGPIGP Посмотреть сообщение
становится угрожающе статической
Иногда лучше вообще ничего не писать, чем писать "хрень".

Цитата Сообщение от IGPIGP Посмотреть сообщение
Тут перечислены 2 случая, но не через запятую а с союзом "и":
По-моему вы мне мозги полоскаете. Нет?

Цитата Сообщение от IGPIGP Посмотреть сообщение
a) int a = 123;
Это именно инициализация, а не присвоение.

Цитата Сообщение от IGPIGP Посмотреть сообщение
оставляет только догадываться о чём он пытался спросить.
Он не знает материал, поэтому не может сформулировать точно вопрос.

По идее, находится кто нибудь, кто чисто по человечески догадывается (хотя бы примерно) о чем речь.
Ну или переспрашивает, наталкивая новичка на более корректные вопросы...

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

В этом заключается суть "с++ раздел для новичков", разве нет?
Yandex
Объявления
01.02.2015, 01:41     Когда надо использовать списки инициализации, а когда можно заменить их констуктором по умолчанию?
Ответ Создать тему
Опции темы

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