Задать вопрос
@oftywave

Инициализация элемента к нулю?

время от времени пользусь таким методом
HWND window = HWND();
std::string string = std::string();
HRESULT res = HRESULT();


но не совсем понимаю как это работает, насколько я знаю это присваивает ноль.
хотелось бы узнать побольше об этом методе от вас.
  • Вопрос задан
  • 249 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 3
@Mercury13
Программист на «си с крестами» и не только
1, 3. Просто совпадение, обычно потому, что компиляторы в отладочном режиме всё инициализируют нулями (проще отлаживать). На это нельзя рассчитывать, пиши HWND window = nullptr.
2. Лучше написать std::string str;, да и всё. Можно рассчитывать, что будет пустая строка.

Почему 1,3 плохо, а 2 хорошо? Потому что HWND и HRESULT — синонимы для встроенных типов (не то указатель, не то число того же размера), а у них конструктор по умолчанию ничего не делает. А string — нормальный себе объект.
Ответ написан
@MarkusD Куратор тега C++
все время мелю чепуху :)
Процесс инициализации объекта является довольно сложным и местами запутанным.

В контексте вопроса полезно будет рассмотреть два отдельных вида инициализации: инициализацию по умолчанию и инициализацию значением.

Поведение инициализации по умолчанию говорит что для сложных типов будет выбран подходящий конструктор, а для тривиальных типов ничего сделано не будет. Эти правила говорят о том, что обязательная процедура инициализации объекта не всегда приводит к его фактической инициализации. Для тривиальных типов инициализация является фиктивной, а созданный объект остается неинициализированным.
Тут можно обратить внимание и на то, что в поведении инициализации по умолчанию вообще ничего не говорится о вызове конструктора тривиального типа. Просто говорится о том, что при инициализации ничего не делается.
Мы часто путаем вызов конструктора и инициализацию, т.к. смысл их близок, а сильные различия не всегда вспоминаются. Фактически конструктор тривиального типа вообще не фигурирует в процессе инициализации, но бывает проще запомнить что это именно он фиктивный и ничего не делает.

Интереснее будет рассмотреть поведение инициализации значением.
Форма T() может привести к вызову конструктора с пустым std::initializer_list, к вызову конструктора по умолчанию, а может свестись к инициализации по умолчанию в том случае, если конструктор по умолчанию удален или по своим причинам пропущен в пользовательском типе.
Каждый, кроме последних двух, пункт поведения инициализации значением оперирует словом class, т.е. имеет отношение только к сложным типам. Последний пункт описывает поведение инициализации для всех неописанных выше случаев как инициализацию нулем.
И именно инициализация нулем написана в примере вопроса.

Форма T() хорошо подходит для инициализации локальных временных объектов, а для инициализации именованных объектов лучше подходит форма T object {};.
Форма T object = T();, на самом деле, выполняет инициализацию копией, где в качестве копии используется локальный временный объект T().

В результате, конкретно конструкция T() или T{} может привести к вызову конструктора по умолчанию или вызову конструктора от пустого std::initializer_list для сложного типа и инициализацию нулем для простого типа.
Это - очень полезное поведение в метапрограммировании, где у тебя может быть шаблон типа, в котором требуется по значению разместить объект с типом параметра шаблона. Этот объект требуется инициализировать правильным образом, но ты никак не можешь классифицировать тип, передаваемый параметром шаблона. Благодаря инициализации значением можно не задаваться вопросами природы типа из шаблонного параметра.

Но увлекаться этим подходом тоже не стоит. Я предпочту вариант std::string string; варианту std::string string = std::string(); потому что для std::string инициализация по умолчанию сделает точно то же самое, будет эффективнее (т.к. во втором случае будет копирование) и будет понятнее.
Код HRESULT res = HRESULT(); стоит заменить на инициализацию одним из базовых значений. Например - кодом S_OK. Это создаст понимание базового состояния программы в месте определения переменной. Тип HRESULT имеет очень сильную семантику и сразу о многом говорит подготовленному читателю.
Только HWND window = HWND(); или HWND window{}; на самом деле смотрится к месту, т.к. в WinAPI нет предопределенного начального значения и объект проще провести через стандартную инициализацию значением. Уж этот краевой случай разработчики WinAPI должны предусмотреть.
Ответ написан
maaGames
@maaGames
Погроммирую программы
Вызывается конструктор по умолчанию. Для указателя это 0, он же nullptr.
HWND и HRESULT это void*.
Это корявая запись в стиле C#. В С++ лучше инициализирвоать сам создаваемый объект, чтобы избежать копирования (не в данном случае, а вообще, если объект имеет сложный тип). Т.е. писать сразу:
HWND window(); или HWND window = nullptr;
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы