Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.96/109: Рейтинг темы: голосов - 109, средняя оценка - 4.96
6 / 6 / 2
Регистрация: 12.02.2012
Сообщений: 224
1

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

09.09.2012, 20:23. Показов 20899. Ответов 24
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
1)Любезные,скажите когда надо исп. списки инициализации, а когда можно заменить констуктором по умолчанию?
2) правильно ли утверждение,что списки инициализации можно заменить к.по умолчанию?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.09.2012, 20:23
Ответы с готовыми решениями:

Когда стоит использовать класс, а когда лучше обойтись без них?
Когда стоит использовать класс, а когда лучше обойтись без них? Когда следует использовать...

Когда нужно использовать &ссылки ,а когда *указатели?
Желательно с примерами

Когда использовать WinAPI, а когда функции языка?
Не совсем понимаю, когда нужно использовать WinAPI в приложении, а когда функционал самого ЯП...

Когда использовать указатели, а когда передачу по ссылке?
Когда использовать указатели, а когда передачу по ссылке?

24
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
09.09.2012, 20:32 2
Уточните-ка, какие именно списки инициализации вы имеете ввиду? Списки инициализации объектов? Или список инициализации конструктора?
0
6 / 6 / 2
Регистрация: 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();
    }
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
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'};
Ну а теперь ответьте на вопрос: как можно список инициализации заменить конструктором по умолчанию? И как можно воду заменить жареной картошкой? Это я к тому, что вещи это разные. Либо я не понял вопроса. Попробуйте пояснить, что вы подразумеваете под подобной заменой?
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
09.09.2012, 20:57 5
Цитата Сообщение от RASHFor Посмотреть сообщение
1)Любезные,скажите когда надо исп. списки инициализации, а когда можно заменить констуктором по умолчанию?
2) правильно ли утверждение,что списки инициализации можно заменить к.по умолчанию?
Список инициализации, например, - единственный выход для инициализации не статических констант класса. Их можно объявить, в теле объявления (сигнатуре) класса, а определить в конструкторе, применив инициализацию списком.
зы для случая приведенного Вами, можно легко провести инициализацию в теле конструктора присвоением. И компилятор это примет. Тут нет разницы. А вот константу так инициализировать не даст.)
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
09.09.2012, 21:03 6
IGPIGP, да банальнейший пример - вызов конкретного конструктора базового класса можно сделать только в списке инициализации.
1
6 / 6 / 2
Регистрация: 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;
};
П.С Вопросы скорей всего тупые и вас бесят,но я так быстрее пойму,если буду знать ответы.Спс,за терпение.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
09.09.2012, 21:14 8
RASHFor, да, это конструктор. С двумя параметрами. Один из них (второй) имеет значение по умолчанию. Это значит, что конструктор может быть вызван как с одним, так и с двумя аргументами. В первом случае вызов Foo bar(10) эквивалентен вызову Foo bar(10, 0) (если второй аргумент явно не указан, будет передано его значение по умолчанию). После двоеточия через запятую идёт список инициализации конструктора, по факт - вызов конструкторов других объектов.
2
6 / 6 / 2
Регистрация: 12.02.2012
Сообщений: 224
09.09.2012, 21:18  [ТС] 9
Спасибо,вроде въехал.трошки.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
09.09.2012, 21:34 10
Тут почитайте: Двоеточие в конструкторе
Явное наследование конструкторов
1
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
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;
};
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
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();
}
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
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;
}
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
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_; //не получится
}
Ваше "не получится" - это присвоение, а не инициализация.

Очевидно, что раз мембер - константа, то присвоить ему новое значение уже нельзя.
Только к инициализации это вообще не имеет никакого отношения
0
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
31.01.2015, 22:05 15
hoggy, ответте на мой вопрос, пожалуйста. Похоже, в данной ветке вы самый "прошаренный"
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
31.01.2015, 22:10 16
Цитата Сообщение от hoggy Посмотреть сообщение
Ваше "не получится" - это присвоение, а не инициализация.
Холливар? Не интересует.
Цитата Сообщение от hoggy Посмотреть сообщение
Она была и остается обычным мембером класса.
А кто спорит. Но увсех мемберов этого пола:
const int a = 10;
для всех экземпляров будет одно значение: 10
А присвоение при объявлении и в теле конструктора это инициализация. Хотя синтаксически - присвоение.

Не по теме:

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

0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
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, что бы гарантировать это положение.
0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
01.02.2015, 00:49 18
Цитата Сообщение от hoggy Посмотреть сообщение
В общем случае это может быть нужно тогда,
когда требуется гарантировать неизменность данных.
Вы говорите о необходимости статических констант? А я спросил о том, зачем может понадобиться куча одинаковых по значению копий (мемберов как вы говорите).
Фраза:
Цитата Сообщение от IGPIGP Посмотреть сообщение
каждый будет иметь свою копию в отличие от настоящей статической константы.
в ней ясно, что речь не о статической константе, а о константе члене. И о бессмысленности её инициализации литералом, а не внешним параметром. Но Вы хотите не увидеть и пишете:
Цитата Сообщение от hoggy Посмотреть сообщение
Она была и остается обычным мембером класса.
Хотя нигде не говорилось иного.
Ещё фраза:
Цитата Сообщение от IGPIGP Посмотреть сообщение
А присвоение при объявлении и в теле конструктора это инициализация. Хотя синтаксически - присвоение.
Тут перечислены 2 случая, но не через запятую а с союзом "и":
a) int a = 123;//глобально, локально, как угодно
б) объявление в классе, а инициализация присвоением в конструкторе. Это вопрос скользкий и в общем случае наверное инициализации тут нет, а есть присваивание. Не буду спорить, - неточно сказал.
Но вопрос ТС:
Цитата Сообщение от RASHFor Посмотреть сообщение
а когда можно заменить конструктором по умолчанию?
оставляет только догадываться о чём он пытался спросить. Возможно о том, что когда в членах определены конструкторы преобразования и не определены конструкторы по умолчанию, то инициализация в списке, это способ гарантирующий инициализацию до вызова любого из методов. Однако, судя по тому как вопрос задан, это наверное и хорошо, что никто не стал об этом говорить. Надеюсь продолжения не будет.
0
0 / 0 / 0
Регистрация: 24.01.2015
Сообщений: 6
01.02.2015, 01:39 19
Простое правило, которое использую лично я, если это конструктор в котором просто инициализируются данные, то - это список инициализации, если есть выделение памяти или же какие-то еще нюансы, тогда описываю все в конструкторе, а по-поводу консруктора по-умолчанию, его всегда надо писать по-умолчанию и через тот же список инициализации задавать значения по-умолчанию.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
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 Посмотреть сообщение
оставляет только догадываться о чём он пытался спросить.
Он не знает материал, поэтому не может сформулировать точно вопрос.

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

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

В этом заключается суть "с++ раздел для новичков", разве нет?
1
01.02.2015, 01:41
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.02.2015, 01:41
Помогаю со студенческими работами здесь

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

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

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

Когда нужно использовать ссылку с out, а когда с ref
Не давно начал учить С# но не могу понять когда надо использовать оut или ref , я так понимаю что...


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

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