Reddit - cpp - Якщо у моїх структурах класів є конструктори за замовчуванням

Можливо. Наступного разу, коли зіткнусь із ситуацією, я з тобою подумаю і зв’яжусь з тобою.

структурах

Це щось на кшталт того, що C ++ не дозволяє декларувати та ініціалізувати об'єкти окремо (а також, можливо, поганий дизайн). Є й інші мови, де це не так.

Я не думаю, що має сенс для варіанту чи кортежу (і, за розширенням, пари) мати конструктори за замовчуванням.

Хіба неініціалізований об’єкт - це просто деяка кількість байтів у пам’яті, значення яких не означають нічого корисного в контексті будь-якого типу, яким повинен бути об’єкт?

У мовах, якими я користувався, що дозволяє окреме оголошення/ініціалізацію, ваш код не компілюється, якщо компілятор не зможе довести, що ви ніколи не отримуєте доступ до неініціалізованого об’єкта.

EDIT: Крім того, C ++ не дозволяє вам мати нетривіальні неініціалізовані об'єкти. Просто оголошення об’єкта викликає його конструктор за замовчуванням.

EDIT 2: нетривіальні неініціалізовані об’єкти

Крім того, C ++ не дозволяє мати неініціалізовані об'єкти

Це очевидно неправильно. Простий локально оголошений int i; є зустрічним прикладом. І звичайно ж те саме стосується і нестандартних тривіальних типів.

Я не впевнений, що розглядав би змінні примітивних типів об'єктів. Однак ти маєш рацію, коли йдеться про тривіальні типи.

З цим зрозумілий стандарт С ++: екземпляри примітивних типів є об’єктами (§6.6.2/1). Спрощено, майже все з адресою пам'яті та типом є об’єктом у C ++. Помітним винятком є ​​функції, які не є об'єктами, навіть якщо вони займають пам'ять.

Не можу посперечатися зі стандартним ¯ \ _ (ツ) _/¯.

RAII не робить цього простим в обробці.

Це щось на кшталт того, що C ++ не дозволяє оголошувати та ініціалізувати об'єкти окремо

Ми говорили те саме.

Ви маєте рацію - я не помітив цього при першому прочитанні.

Спасибі. Мені подобається поняття "порожній стан".

Як правило, чим більше стан об’єкта, тим важче його міркувати. Якщо ви можете уникнути порожнього стану, я пропоную вам це зробити. Швидше за все, у вас є свого роду проблема XY, і є інший спосіб її вирішення, крім порожнього стану. Натомість прагніть до того, щоб ваші об’єкти завжди були самоузгоджені. Визначте об’єкт за його інваріантами та переконайтесь, що жоден загальнодоступний інтерфейс об’єкта не допускає порушення цих інваріантів.

Якщо ви просто створюєте об'єкт з купою полів і купою геттерів/сеттерів для тих самих полів, то вам, мабуть, просто потрібна змінна BLOB-адреса даних, яка найкраще виражається через загальнодоступний об'єкт (яка структура зазвичай використовується експрес). Поміркуйте

Я зазвичай це роблю, відокремлюючи дані від поведінки, збираючи дані у структурах (зазвичай незмінні) та функціональності в функціях constexpr (чистих).

Надзвичайно захоплююча стаття про проблеми XY. Я ніколи про це не чув. Спасибі.

Чи слід видаляти автоматично згенерований, якщо предмет, який ваш клас намагається змоделювати, не має такого стану? Також це буде звучати як справді тупе запитання, але як я це можу зробити?

Ви можете позначити конструктори як видалені.

/ u/ImmediateAntelope3 має рацію, але якщо вам це дійсно потрібно, ви можете позначити його як видалений або зробити приватним (до C ++ 11)

Що має сенс. Дякуємо за роз'яснення.

Якщо ви визначите інший конструктор, ваш об'єкт не матиме конструктора за замовчуванням.

Розумію. Якщо ви хочете обидва, вам потрібно чітко їх визначити?

Розумію. Дякуємо за роз'яснення.

Тут є фундаментальний компроміс.

По-перше, конструктор за замовчуванням полегшує інтеграцію з іншими бібліотеками. Наприклад, якщо ви хочете змінити розмір пам'яті для вектора, вам потрібна побудова за замовчуванням для ваших об’єктів. Якщо вам потрібно використовувати оператор [] на карті, також.

Але додавання конструктора за замовчуванням там, де немає сенсу, також викликає занепокоєння, оскільки ви можете легше порушити інваріанти для об’єкта. А саме, ви зробили частково сформовані об’єкти законними у своєму коді.

Наприклад, ви не можете мати, можливо, осіб за замовчуванням, оскільки це не мало б сенсу. Якщо ви це зробите, тепер вам доведеться захарастити ВСІ функції в класі для перевірки логіки щодо порожнечі, якщо ви хочете відновити цю безпеку, ускладнивши читання коду. Ще гірше, додаючи нові функції, ви можете забути перевірку на порожнечу, введення помилок.

Об'єкти, побудовані за замовчуванням у невизначеному стані, зазвичай називаються частково сформованими при побудові за замовчуванням. Я б уникав, коли це можливо, якщо це не є вимогою.

Ви завжди можете затримати побудову об’єкта за допомогою std: optional. Таким чином, ви можете за замовчуванням створити необов’язковий і пізніше заповнити його чимось, що має сенс. Наприклад. у випадку з вектором, який ви попередньо змінили розмір, ви могли б мати вектор>, і він би виконував завдання для більшості випадків використання, ціною жертвуючи трохи місця (необов’язково більше, ніж Т, за конкретним модулем добре відомий оптимізації, такі як кодування необов’язкової порожнечі в самому T).

Загалом, є компроміси, але я вважаю за краще не використовувати конструктор за замовчуванням, коли це не має сенсу, а використовувати альтернативи, такі як необов’язкові, коли потрібно адаптувати речі. Однак спробуйте надати конструктори за замовчуванням, якщо вони мають сенс, вони полегшують інтеграцію з іншими компонентами.