_DEN_ Добавить в Foo конструктор и инициализировать вручную. А вообще надо бы багрепорт Микрософту задвинуть...
green А гте ты увидел value-инициализацию? Здесь default. green Не-а... в данном случае это равносильно A a; Где об этом сказано в стандарте - сразу не найду, но об этом упоминает господин Страуструп - что опять-таки в целях оптимизации компилятор не обязан действовать по сценарию: Код (Text): A temp; // конструктор A::A() A a(temp); // конструктор A::(const A&) а может сразу: Код (Text): A a; // конструктор A::A() Вооще, конструктор копирования - вещь очень мутная, лучше всего не закладываться на его сторонние эффекты, ибо он может быть употреблен или нет - в зависимости от настроения компилятора. Например, возвращаемое функцией значение, если это объект класса, может привести к вызову конструктора копирования. А может и не привести, что особенно вероятно если функция заинлайнена. (По моим наблюдениям, даже если и не заинлайнена, но возвращенное значение используется как инициализатор - такая конструкция, в зависимости от компилятора и режима оптимизации может привести к вызову конструктора копирования ноль, один или два раза.)
Ustus В коде, приведённом _DEN_, именно value-инициализация. В случае Код (Text): A a = A(); компилятор действительно может исключить копирование, выполнив инициализацию "на месте", но семантически это остаётся value-инициализацией, в отличие от Код (Text): A a; Выдержка из Стандарта (8.5):
green еще раз повторю - нет! value- была бы если бы: Код (Text): A b; // - default A a = b; // или A a(b);, что одно и то же. - value Собcтвенно, вид инициализации здесь не важен, потому что value-инициализация копирует значения из объекта, созданого по default, а на этот счет однозначно сказано (оттуда же): о чем я и говорю. Впрочем для этого мне и стандарта не надо, достаточно здравого смысла, C - это ведь не Basic, в Си настоятельно рекомендуется не уповать на умолчание. кстати, здесь же и ответ на вопрос:
Ustus расскажи тогда чем отличается Код (Text): int x; и Код (Text): int x = int(); и почему в первом случае - варнинг, что переменная не инициализирована, а во втором -нет?
Ustus Код (Text): int main() int i; //int i = int(); cout << i << '\n'; return 0; } отличаются. и основательно VC8.0, VC6.0, Comeau 4.3.9. Intel под рукой нет.
Ustus Извини, но по-моему ты неправ. В выражении Код (Text): A a = A(); сначала создаётся анонимный объект A(), которым затем инициализируется объект а. Анонимный объект создается value-инициализированным. Собственно, такая двойная инициализация необходима из-за синтаксической накладки: выражение Код (Text): A a(); означает декларацию ф-ции, а не объекта. Впрочем, оптимизатор выбросит вторую инициализацию. В случае динамического создания все проще: new A; // default initialization new A(); // value initialization Инициализатор с пустым набором скобок и отсутствие инициализатора - это не одно и тоже. В С да, но не в С++, разве не так? И ничего плохого в этом нет, если не злоупотреблять. Взять хотя бы аргументы по умолчанию - весьма полезная штука.
_DEN_ Если тебе нечего сказать, не надо ничего говорить RedLord Хм... а ведь действительно отличаются... просто сразу не попробовал. Интересный эффект. Но в данном случае речь не об этом, а о том, что объект вообще не инициализируется. green Возможно, ты прав. В теории. Но меня больше интересует практическая сторона вопроса. И еще. Ты упорно рассматриваешь объект класса. Да, для него будет обязательно вызван конструктор. Но проблема-то не в нем, а в его поле. Которое интегрального типа. И стандарт не гарантирует, что там будет что-то путное, если оно не статическое и не задано явно. Я считаю, что это логично. Если хочешь меня опровергнуть, приведи стандарт, где написано, что поля value-инициализируемого объекта тоже value-инициализируемые. Я думаю, что в их случае рулит default, если в конструкторе явно не объявлено обратное. В любом случае я не нашел в страшном и ужасном стандарте подтверждения ни тому, ни другому. А ты попробуй - уверен, что большинство компиляторов никакого временного объекта не создадут. На чем основано это мнение, чем подтверждается, что из этого следует? (я не издеваюсь , мне в самом деле интересно, пока я не вижу никакой разницы, кроме чисто теоретической ) Я имел ввиду оба. Более того, уверен, что глюки типа описываемого - тяжелое наследие Си(без плюсов), оберегаемое в целях совместимости. ну, это-то тут не при чем, это никакое не умолчание, а просто удобная сокращенная запись. Код генерится одинаковый в обоих случаях.
Ustus С каких пор компиляторы стали первоисточником? C и C++ это два совершенно разных языка. А как по-твоему это переводится? An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized Ты Леху Косого знаешь? А Васю Бульдозера? А, так ты чо, не местный что ли? )))
Ustus См. посты #6, #20 этого топика. Если у объекта (здесь и далее имеется в виду объект любого, не только классового типа) нет конструктора, то value-инициализация обеспечивает value-инициализацию его и его членов, если таковые имеются. Если же конструктор имеется, тогда он отвечает за инициализацию содержимого объекта. В этом случае возможно неопределённое значение полей. Я и говорю - оптимизатор исключит копирующую инициализацию временным объектом, т.е. сделает единственную in-place инициализацию. Но с сохранением семантики value-инициализации, конечно. 1. 2. Как видно, разница весьма и весьма практическая. Впрочем, во всём этом можно убедиться, посмотрев код, сгенерированный "стандартным" компилятором (IMHO, лучше всего Comeau, хотя за Интелом я тоже не замечал наплевания на Стандарт).
_DEN_ Это я к тому, что такую инициализацию можно рассматривать только в теории. Это так, но принципом умолчания лучше не пользоваться ни в том, ни в другом. ИМХО Это переводится: Объект, инициализатор которого - пустые скобки будет инициализировани по значению. Про его базы и члены ни слова. Не, я знаю только Васю Косого и Леху Бульдозера green Ага, вот это ближе к теме... Впрочем это логично. Вобщем, если хочешь знать, ты меня убедил. В смысле стандарта. Но в смысле оптимальности кода обнуление POD выглядит избыточно, поскольку лучше уж я его сам проинициализирую, а если так, то что - два раза инициализировать? А вот для проверки: Код (Text): struct A1 { int i; }; struct A2 { int i; A2() {} }; int main() { A1 a11, a12 = A1(); A2 a21, a22 = A2(); std::cout << a11.i << ' ' << a12.i << '\n' << a21.i << ' ' << a22.i << '\n'; return 0; } В VC 7.0 все четыре числа - крокозяблики, хотя вроде как исходя из стандарта - a12-то точно должно быть 0. На BCB 5.0 (вот это истинное ЗЛО и нестандартщина, а VC - это так... ) аналогично. Других под рукой нет, погоняйте, pls, кому не лень. Ну а если мое личное мнение, безотносительно к стандарту - бред все это. Ничего компилятор не должен делать, сверх того, что ему прямо скажут. Иначе это уже не ЦеПеПе получится, а Пролог какой-то...
Ustus Если инициализировать вручную, добавив в класс конструктор, то компилятор не будет вставлять никакой неявной инициализации. Так что избыточности нет. Нда... А в VC8, Intel9 a12.i == 0, как и полагается. Раз так, тогда действительно лучше инициализировать вручную... или пользоваться нормальным, проверенным компилятором. Ну, мы здесь прямо говорим компилятору делать инициализацию, указывая пустой инициализатор. А вообще, если компилятор будет делать _только_ то, что ему скажут, то получится Ассемблер, типа HLA. И никакой оптимизации. ЯВУ для того и придуманы, чтобы избавить программиста от необходимости контролировать рутинные, низкоуровневые операции. Но С++ уникален тем, что в нём нет принудительного избавления - можно работать на любом уровне - от абстракций проектирования до практически асмовского контроля за кодом.
green А остальные? В смысле a11, a21, a22? Да... похоже, семерка уже морально устарела Я вообще-то всегда инициализирую явно... меньше шансов для врага согласен. С++ уникален тем, что сочетает низкоуровневую битовую мясорубку с заумной высокоуровневой мозгокруткой Зато, видишь, как интересно!
Ustus мысль достаточно трезвая. именно поэтому Код (Text): struct S { std::string s; int i; }; int main() { S s; // так вызовется конструктор только s, i - останется неинициализированным //S s = S(); // а вот это и есть _явная_ инициализация return 0; } Стандарт предоставляет свободу выбора приведу цитату дальше про мемберы в случае Код (Text): S s;// так вызовется конструктор только s, i - останется неинициализированным но в случае Код (Text): S s = S(); вступают иные правила игры.