Я кодирую небольшую библиотеку числового анализа в С++. Я пытаюсь реализовать с использованием последних возможностей С++ 11, включая семантику перемещения. Я понимаю дискуссию и ответ на следующий пост: С++ 11 rvalues и перемещение семантики (return statement), но есть один сценарий, который я все еще пытаюсь чтобы обернуть мою голову.
У меня есть класс, назовите его T
, который полностью оснащен перегруженными операторами. У меня также есть конструкторы копирования и перемещения.
T (const T &) { /*initialization via copy*/; }
T (T &&) { /*initialization via move*/; }
Мой клиентский код сильно использует операторы, поэтому я стараюсь, чтобы сложные арифметические выражения получали максимальную выгоду от семантики перемещения. Рассмотрим следующее:
T a, b, c, d, e;
T f = a + b * c - d / e;
Без семантики перемещения мои операторы каждый раз создают новую локальную переменную, используя конструктор копирования, поэтому их всего 4 копии. Я надеялся, что с семантикой перемещения я мог бы уменьшить это до 2-х копий плюс некоторые ходы. В версии в скобках:
T f = a + (b * c) - (d / e);
каждый из (b * c)
и (d / e)
должен создать временный обычным способом с копией, но тогда было бы здорово, если бы я мог использовать один из этих временных рядов для накопления оставшихся результатов только с ходами.
Используя компилятор g++, я смог это сделать, но я подозреваю, что моя техника может быть небезопасной, и я хочу полностью понять, почему.
Вот пример реализации для оператора сложения:
T operator+ (T const& x) const
{
T result(*this);
// logic to perform addition here using result as the target
return std::move(result);
}
T operator+ (T&& x) const
{
// logic to perform addition here using x as the target
return std::move(x);
}
Без вызовов std::move
, тогда используется только версия const &
для каждого оператора. Но при использовании std::move
, как и выше, последующая арифметика (после самых внутренних выражений) выполняется с использованием версии &&
каждого оператора.
Я знаю, что RVO может быть заблокирован, но по очень вычислительно дорогостоящим реальным проблемам кажется, что выигрыш немного перевешивает отсутствие RVO. То есть, за миллионы вычислений я получаю очень небольшое ускорение, когда включаю std::move
. Хотя, честно говоря, достаточно быстро. Я просто хочу полностью понять семантику здесь.
Есть ли хороший С++-Гуру, который готов потратить время, чтобы объяснить, простым образом, и почему мое использование std:: move здесь плохо? Большое спасибо заранее.