Как я могу быть уверен, что процедура использует преимущества (N) RVO?

StackOverflow https://stackoverflow.com//questions/9621720

Вопрос

Я хотел бы убедиться, что мои процедуры используют (N) RVO, когда это возможно.Помимо синтаксического анализа результирующей дизассембляции, есть ли что-то, что я могу сделать или проверить, компилируется ли процедура с (N) RVO?На данный момент меня больше всего интересуют MSVC и GCC.

Это было полезно?

Решение

Нет, не совсем.

Однако вы можете следовать рекомендациям при написании своего кода.


Оптимизация Безымянного возвращаемого значения

Это в значительной степени срабатывает каждый раз, когда вы возвращаете временное значение, даже в режиме отладки.

return MyObject(....);

Оптимизация Именованного возвращаемого значения

Это в значительной степени срабатывает каждый раз, когда функция всегда возвращает один и тот же временный объект:

MyObject func() {
  MyObject result;
  if (...) { return result; }

  result.push(0);
  return result;
}

Вы можете смешать их, но компилятору становится практически невозможно применить RVO в этом случае:

MyObject func() {
  MyObject result;
  if (...) { return MyObject(...); }

  return result;
}

Здесь, вероятно, один возврат выиграет от RVO, а другой - нет.И я бы поставил на то, что первый будет оптимизирован, потому что вы застряли бы, если бы создавали умозрительно result в обратном слоте, и вдруг понадобится взять if филиал.Обратите внимание, что простое изменение порядка инструкций просто работает:

MyObject func() {
  if (...) { return MyObject(...); }

  MyObject result;

  return result;
}

Итак, эмпирическое правило для NRVO заключается в том, что не должно быть никаких return заявление между заявлением о result и тот return result; оператор, который возвращает что-либо иное, чем result сам по себе.


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

И вы также облегчаете чтение своего кода, поскольку не объявляете переменные до того, как узнаете, что они вам действительно нужны!

Другие советы

Вы можете добавить методы отладки в деструктор:

struct A
{
   ~A() { cout << "destructor called"; }
};

A foo()
{
   A a;
   return a;
}
.

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

Возможные способы думать:

  1. Реализация механизма подсчета ссылок в вашем классе, который отслеживает количество экземпляров, созданных через класс, что-то в значительной степени похоже на генеракодицетагкод, таким образом, вы можете обнаружить дополнительные копии вашего класса, созданного и удаленного, еслиCopy Enision не происходит.

  2. Вы могли бы просто поставить следы отладки в Copy Constructor и Destructor для вашего класса, если выяснение копирования не происходит, вы увидите много преследующих преследующих копий и отладки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top