Подтвердить что ты не робот

Предупреждение GCC NRVO/RVO

Есть ли какое-либо предупреждение, которое позволяет нам узнать, выполнено или нет NRVO/RVO в GCC?

Я обнаружил, что -fno-elide-constructors отключает NRVO/RVO, но NRVO/RVO имеет свои собственные условия и иногда их не происходит. Необходимо знать, существует ли NRVO/RVO, чтобы понять, когда происходит дополнительная копирование.

Мне особенно интересны функции компиляции. Было бы неплохо, если бы был какой-то конкретный #pragma GCC... (который сразу активирует диагностику сразу после себя) или что-то, используя механизм статического утверждения.

4b9b3361

Ответ 1

Мне неизвестно какое-либо конкретное диагностическое сообщение gcc или другой метод, который легко может решить вашу задачу. Как вы узнали, -fno-elide-constructors отключит копирование/перемещение элит, так что вы наверняка будете знать, что (N) RVO не произойдет в этом случае по крайней мере.

Тем не менее, быстрый взгляд на пункт 31 раздела 12.8 этот рабочий проект С++ 11 гласит, что:

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

  • в операторе return в функции с типом возвращаемого класса, когда выражение является именем энергонезависимого автоматического объекта (другое чем параметр функции или catch-clause) с тем же cv-unqualified тип как возвращаемый тип функции, операция копирования/перемещения может быть опущено путем создания автоматического объекта непосредственно в функции возвращают значение

...

  • , когда объект временного класса, который не был привязан к ссылке (12.2), будет скопирован/перенесен в объект класса с тем же cv-unqualified тип, операция копирования/перемещения может быть опущена построение временного объекта непосредственно в цель omitted copy/move

...

Когда выполняется копирование/перемещение, локальный автоматический объект совпадает с временным (возвращаемым) объектом, который, в свою очередь, совпадает с объектом "хранения" (где хранится возвращаемое значение). Таким образом, локальный автоматический объект совпадает с объектом хранения, что означает, что сравнение указателей будет равно true. Простой пример, чтобы продемонстрировать это:

#include <iostream>
#include <vector>

std::vector<int> testNRVO(int value, size_t size, const std::vector<int> **localVec)
{
   std::vector<int> vec(size, value);

   *localVec = &vec;

   /* Do something here.. */

   return vec;
}

int main()
{
   const std::vector<int> *localVec = nullptr;

   std::vector<int> vec = testNRVO(0, 10, &localVec);

   if (&vec == localVec)
      std::cout << "NRVO was applied" << std::endl;
   else
      std::cout << "NRVO was not applied" << std::endl;
}

Включение/выключение -fno-elide-constructors изменяет печатаемое сообщение, как ожидалось. Примечание: в строгом смысле сравнение указателей может зависеть от поведения undefined, когда (N) RVO не происходит, поскольку локальный автоматический объект не существует.

Выполнение сравнения указателей добавит крейт, но с преимуществом независимости от компилятора.