Семантика перемещения и передача по R-значению в перегруженной арифметике

Я кодирую небольшую библиотеку числового анализа в C ++. Я пытался реализовать с использованием новейших функций C ++ 11, включая семантику перемещения. Я понимаю обсуждение и топ-ответ в следующем посте:C ++ 11 значения и путаница в семантике перемещения (оператор return) , но есть один сценарий, который я все еще пытаюсь обернуть вокруг.

У меня есть класс, назовите это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, Хотя, честно говоря, это достаточно быстро без. Я действительно просто хочу полностью понять семантику здесь.

Есть ли добрый C ++ Guru, который хочет найти время, чтобы объяснить простым способом, является ли и почему мое использование std :: move плохой вещью здесь? Спасибо заранее.

Ответы на вопрос(3)

Ваш ответ на вопрос