﻿# V832\. It's better to use '\= default;' syntax instead of empty body\.

Если в классе специальные функции объявляются с '\= default', класс остается тривиально копируемым\. Это потенциально поможет копировать и инициализировать такой класс более оптимально\.

Правила формирования специальных функций сложные\. Поэтому при написании классов/структур лучшим решением будет определить явно некоторые из них для лучшего понимания кода\. Вот примеры таких специальных функций: [конструктор по умолчанию](https://en.cppreference.com/w/cpp/language/default_constructor), [конструктор копирования](https://en.cppreference.com/w/cpp/language/copy_constructor), [оператор копирования](https://en.cppreference.com/w/cpp/language/copy_assignment), [деструктор](https://en.cppreference.com/w/cpp/language/destructor), [конструктор перемещения](https://en.cppreference.com/w/cpp/language/move_constructor), [оператор перемещения](https://en.cppreference.com/w/cpp/language/move_assignment)\.

```cpp
struct MyClass
{
  int x;
  int y;
  MyClass() {}
  ~MyClass() {}
};
```

или так:

```cpp
// header
struct MyClass
{
  int x;
  int y;
};

// cpp-file
MyClass::MyClass() {}
MyClass::~MyClass() {}
```

Такие функции \(конструктор по умолчанию и деструктор в примере\) программист определяет с пустым телом\. Однако при таком подходе класс может стать нетривиально копируемым, из\-за чего компилятор не всегда сможет сгенерировать более [оптимальный код](https://godbolt.org/z/PM1sY3Wh8)\. Поэтому C\+\+11 вводит синтаксис '\= default' для специальных функций:

```cpp
struct MyClass
{
  int x;
  int y;
  MyClass() = default;
  ~MyClass() = default;
};
```

Помимо того, что компилятор сам сгенерирует тела специальных функций, он сможет вывести спецификаторы '[constexpr](https://en.cppreference.com/w/cpp/language/constexpr)' и '[noexcept](https://en.cppreference.com/w/cpp/language/noexcept_spec)' для них автоматически\.

Стоит отметить, что при переносе определения специальных функций из тела класса компилятор считает их определенными пользователем\. Это может привести к [пессимизации](https://godbolt.org/z/E8eEK65K1), поэтому '\= default' лучше по возможности добавлять непосредственно в теле класса\.

Срабатывание не выдается, если:

* используемый стандарт ниже C\+\+11;
* у конструктора есть список инициализации;
* класс не содержит нестатических полей\.

## Примечание про идиому PIMPL

Определения больших классов внутри заголовочного файла могут многократно увеличивать время компиляции проекта\. Чтобы его сократить, можно вынести реализацию класса в отдельный компилируемый файл, а в заголовочном файле оставить только объявления методов и указатель на реализацию класса\. Такой подход носит название [PIMPL](https://en.cppreference.com/w/cpp/language/pimpl)\. Вот пример такого класса:

```cpp
#include <memory>

// header
class MyClass
{
  class impl;
  std::unique_ptr<impl> pimpl;
public:
  void DoSomething();
  ~MyClass();
};

// cpp-file
class MyClass::impl
{
public:
  impl()
  {
    // does nothing
  }

  ~impl()
  {
    // does nothing
  }

  void DoSomething()
  {
    // ....
  }
};

void MyClass::DoSomething()
{
  pimpl->DoSomething();
}

MyClass::~MyClass() {}
```

Добавление '\= default' к деструктору в теле класса приведет к ошибкам компиляции, т\.к\. деструктор класса 'MyClass::impl' на данном этапе неизвестен \(деструктор нужен для 'std::unique\_ptr'\)\. Поэтому при таком подходе реализация специальных функций переносится в компилируемый файл\.

При переносе определения специальных функций из тела класса их пустые тела также можно заменить на '\= default'\. Это не даст прироста производительности, однако сделает код чище и проще для восприятия:

```cpp
MyClass::~MyClass() = default;
```