Инициализация базовых типов: кто тупит?

Тема в разделе "LANGS.C", создана пользователем _DEN_, 21 май 2007.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    > if no initializer is specified

    A a = A(); Так вот же инишалайзер. (Вот он, вот икс!!!).
     
  2. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    _DEN_
    Именно так. В данном случае должна выполняться value-инициализация.
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Хм... Какой бы такой воркэраунд придумать чтобы студейа не тупила?..
     
  4. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    _DEN_
    Добавить в Foo конструктор и инициализировать вручную. :derisive:
    А вообще надо бы багрепорт Микрософту задвинуть...
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    green

    Написал Саттеру письмо :)
     
  6. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    green
    А гте ты увидел value-инициализацию? Здесь default.

    green
    Не-а... в данном случае это равносильно A a; Где об этом сказано в стандарте - сразу не найду, но об этом упоминает господин Страуструп - что опять-таки в целях оптимизации компилятор не обязан действовать по сценарию:
    Код (Text):
    1. A temp; // конструктор A::A()
    2. A a(temp); // конструктор A::(const A&)
    а может сразу:
    Код (Text):
    1. A a; // конструктор A::A()
    Вооще, конструктор копирования - вещь очень мутная, лучше всего не закладываться на его сторонние эффекты, ибо он может быть употреблен или нет - в зависимости от настроения компилятора. Например, возвращаемое функцией значение, если это объект класса, может привести к вызову конструктора копирования. А может и не привести, что особенно вероятно если функция заинлайнена. (По моим наблюдениям, даже если и не заинлайнена, но возвращенное значение используется как инициализатор - такая конструкция, в зависимости от компилятора и режима оптимизации может привести к вызову конструктора копирования ноль, один или два раза.)
     
  7. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Ustus
    В коде, приведённом _DEN_, именно value-инициализация.
    В случае
    Код (Text):
    1. A a = A();
    компилятор действительно может исключить копирование, выполнив инициализацию "на месте", но семантически это остаётся value-инициализацией, в отличие от
    Код (Text):
    1. A a;
    Выдержка из Стандарта (8.5):
     
  8. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    green
    еще раз повторю - нет! value- была бы если бы:
    Код (Text):
    1. A b;      // - default
    2. A a = b; // или A a(b);, что одно и то же. - value
    Собcтвенно, вид инициализации здесь не важен, потому что value-инициализация копирует значения из объекта, созданого по default, а на этот счет однозначно сказано (оттуда же):

    о чем я и говорю. Впрочем для этого мне и стандарта не надо, достаточно здравого смысла, C - это ведь не Basic, в Си настоятельно рекомендуется не уповать на умолчание.

    кстати, здесь же и ответ на вопрос:
     
  9. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    Ustus

    расскажи тогда чем отличается
    Код (Text):
    1. int x;
    и
    Код (Text):
    1. int x = int();
    и почему в первом случае - варнинг, что переменная не инициализирована, а во втором -нет?
     
  10. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    RedLord
    Ничем.

    Это какой компилятор-то? 8-[
     
  11. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    Ustus
    Код (Text):
    1. int main()
    2.     int i;
    3.     //int i = int();
    4.     cout << i << '\n';
    5.     return 0;
    6. }
    отличаются. и основательно
    VC8.0, VC6.0, Comeau 4.3.9. Intel под рукой нет.
     
  12. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Ustus

    Скажи лучше по какому компилятору ты ориентируешся? Turbo C++ 1.0 ? :-D
     
  13. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Ustus
    Извини, но по-моему ты неправ.
    В выражении
    Код (Text):
    1. A a = A();
    сначала создаётся анонимный объект A(), которым затем инициализируется объект а.
    Анонимный объект создается value-инициализированным.
    Собственно, такая двойная инициализация необходима из-за синтаксической накладки:
    выражение
    Код (Text):
    1. A a();
    означает декларацию ф-ции, а не объекта. Впрочем, оптимизатор выбросит вторую инициализацию.
    В случае динамического создания все проще:
    new A; // default initialization
    new A(); // value initialization

    Инициализатор с пустым набором скобок и отсутствие инициализатора - это не одно и тоже.

    В С да, но не в С++, разве не так? И ничего плохого в этом нет, если не злоупотреблять.
    Взять хотя бы аргументы по умолчанию - весьма полезная штука. :derisive:
     
  14. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    _DEN_
    Если тебе нечего сказать, не надо ничего говорить :)

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

    green
    Возможно, ты прав. В теории. Но меня больше интересует практическая сторона вопроса.
    И еще. Ты упорно рассматриваешь объект класса. Да, для него будет обязательно вызван конструктор. Но проблема-то не в нем, а в его поле. Которое интегрального типа. И стандарт не гарантирует, что там будет что-то путное, если оно не статическое и не задано явно. Я считаю, что это логично. Если хочешь меня опровергнуть, приведи стандарт, где написано, что поля value-инициализируемого объекта тоже value-инициализируемые. Я думаю, что в их случае рулит default, если в конструкторе явно не объявлено обратное. В любом случае я не нашел в страшном и ужасном стандарте подтверждения ни тому, ни другому.

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

    На чем основано это мнение, чем подтверждается, что из этого следует? (я не издеваюсь :) , мне в самом деле интересно, пока я не вижу никакой разницы, кроме чисто теоретической )

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

    :) ну, это-то тут не при чем, это никакое не умолчание, а просто удобная сокращенная запись. Код генерится одинаковый в обоих случаях.
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Ustus

    С каких пор компиляторы стали первоисточником?


    C и C++ это два совершенно разных языка.


    А как по-твоему это переводится? An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized


    Ты Леху Косого знаешь? А Васю Бульдозера? А, так ты чо, не местный что ли? )))
     
  16. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Ustus
    См. посты #6, #20 этого топика. Если у объекта (здесь и далее имеется в виду объект любого, не только классового типа) нет конструктора, то value-инициализация обеспечивает value-инициализацию его и его членов, если таковые имеются.
    Если же конструктор имеется, тогда он отвечает за инициализацию содержимого объекта. В этом случае возможно неопределённое значение полей.
    Я и говорю - оптимизатор исключит копирующую инициализацию временным объектом, т.е. сделает единственную in-place инициализацию. Но с сохранением семантики value-инициализации, конечно.

    1.
    2.
    Как видно, разница весьма и весьма практическая. :)

    Впрочем, во всём этом можно убедиться, посмотрев код, сгенерированный "стандартным" компилятором (IMHO, лучше всего Comeau, хотя за Интелом я тоже не замечал наплевания на Стандарт).
     
  17. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    _DEN_
    Это я к тому, что такую инициализацию можно рассматривать только в теории.

    Это так, но принципом умолчания лучше не пользоваться ни в том, ни в другом. ИМХО :)

    Это переводится: Объект, инициализатор которого - пустые скобки будет инициализировани по значению. Про его базы и члены ни слова.

    Не, я знаю только Васю Косого и Леху Бульдозера :):):)

    green
    Ага, вот это ближе к теме... Впрочем это логично.

    Вобщем, если хочешь знать, ты меня убедил. В смысле стандарта. Но в смысле оптимальности кода обнуление POD выглядит избыточно, поскольку лучше уж я его сам проинициализирую, а если так, то что - два раза инициализировать?

    А вот для проверки:
    Код (Text):
    1. struct A1
    2. {
    3.     int i;
    4. };
    5.  
    6. struct A2
    7. {
    8.     int i;
    9.     A2() {}
    10. };
    11.  
    12. int main()
    13. {
    14.     A1 a11, a12 = A1();
    15.     A2 a21, a22 = A2();
    16.     std::cout << a11.i << ' ' << a12.i << '\n'
    17.               << a21.i << ' ' << a22.i << '\n';
    18.     return 0;
    19. }
    В VC 7.0 все четыре числа - крокозяблики, хотя вроде как исходя из стандарта - a12-то точно должно быть 0. На BCB 5.0 (вот это истинное ЗЛО и нестандартщина, а VC - это так... :) ) аналогично. Других под рукой нет, погоняйте, pls, кому не лень.

    Ну а если мое личное мнение, безотносительно к стандарту - бред все это. Ничего компилятор не должен делать, сверх того, что ему прямо скажут. Иначе это уже не ЦеПеПе получится, а Пролог какой-то...
     
  18. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Ustus
    Если инициализировать вручную, добавив в класс конструктор, то компилятор не будет вставлять никакой неявной инициализации. Так что избыточности нет.
    Нда... А в VC8, Intel9 a12.i == 0, как и полагается.
    Раз так, тогда действительно лучше инициализировать вручную... или пользоваться нормальным, проверенным компилятором.

    Ну, мы здесь прямо говорим компилятору делать инициализацию, указывая пустой инициализатор. :derisive:

    А вообще, если компилятор будет делать _только_ то, что ему скажут, то получится Ассемблер, типа HLA. :)
    И никакой оптимизации.

    ЯВУ для того и придуманы, чтобы избавить программиста от необходимости контролировать рутинные, низкоуровневые операции. Но С++ уникален тем, что в нём нет принудительного избавления - можно работать на любом уровне - от абстракций проектирования до практически асмовского контроля за кодом.
     
  19. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    green
    А остальные? В смысле a11, a21, a22?
    Да... похоже, семерка уже морально устарела :)

    Я вообще-то всегда инициализирую явно... меньше шансов для врага :)

    согласен.

    С++ уникален тем, что сочетает низкоуровневую битовую мясорубку с заумной высокоуровневой мозгокруткой :)
    Зато, видишь, как интересно! :):):)
     
  20. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    Ustus
    мысль достаточно трезвая.
    именно поэтому
    Код (Text):
    1. struct S
    2. {
    3. std::string s;
    4. int i;
    5. };
    6.  
    7. int main()
    8. {
    9. S s; // так вызовется конструктор только s, i - останется неинициализированным
    10. //S s = S(); // а вот это и есть _явная_ инициализация
    11. return 0;
    12. }
    Стандарт предоставляет свободу выбора

    приведу цитату
    дальше про мемберы

    в случае
    Код (Text):
    1. S s;// так вызовется конструктор только s, i - останется неинициализированным
    но в случае
    Код (Text):
    1. S s = S();
    вступают иные правила игры.