В чем причина исключения копирования в C++?

По какой причине стандарт C++ позволяет (требует) компиляторам оптимизировать вызовы конструктора копирования (в определенных случаях), даже если он может содержать наблюдаемые побочные эффекты?

Если я не ошибаюсь, правило "как будто" уже позволяет компиляторам оптимизировать ненужный код, если полученная программа имитирует наблюдаемое поведение абстрактной машины, определенной в стандарте.

Каковы мотивы создания правила исключения? Разве это не создает несоответствия в языке? Это удобно (или нужно)?

2 ответа

В подавляющем большинстве случаев копия, созданная при возврате, будет бесполезной. В остальное время ожидается, что побочные эффекты конструктора копирования будут отменены уничтожением копии. Вещи как std::shared_ptrделать работу с копией, которую можно наблюдать извне, но отменяет ее при уничтожении. Крайне редко конструкция копии объекта имеет побочный эффект, который может быть упущен при копировании. Это стоит того, чтобы избежать снижения производительности в редком случае. Это в принципе никогда не вызывает проблем.

Копирование может означать две разные вещи. "Обязательное исключение копирования" в C++17 - это просто переопределение того, что такое prvalue.

auto foo() { return std::mutex{}; }

Это законно и имеет смысл, потому что внутри функции std::mutexеще не "создан", что касается языка. Не будем останавливаться на этом деле.

В других случаях, например,

auto bar()
{
    std::vector v{1, 2, 3};
    return v;
}

компилятору разрешено исключить копирование / перемещение после проверки того, что семантика копирования / перемещения допустима.

Разве это не создает несоответствия в языке?

Да. Но редко бывает язык, столь зацикленный на согласованности, как C++, исключение копирования выделяется именно потому, что C++ ценит согласованность. Этот компромисс делается ради исключительно большого преимущества: мы не хотим, чтобы люди беспокоились о накладных расходах на производительность при написании функций.

Правило "как если бы" иногда теоретически достаточно для генерации эффективного кода, но на практике оно зачастую чрезвычайно сложно. У компиляторов есть проблемы с оптимизацией в течение длительного времени

delete new int;

тривиально, как это может быть для человека. Мы не хотим ждать, пока оптимизаторы станут идеальными, прежде чем начинать писать функции.

Другие вопросы по тегам