En su caso específico, no, no hay ninguna diferencia.
respuesta detallada:
Bajo el capó, std::move(t)
hace static_cast<typename std::remove_reference<T>::type&&>(t)
, donde T
es tipo de t
(ver §20.2.3/6). En su caso, se resuelve en static_cast<int&&>(nb)
.
forward
es un poco complicado, porque está diseñado para su uso en plantillas (para permitir el reenvío perfecto) y no como una herramienta para convertir lvalue a la referencia de valor.
biblioteca estándar proporciona dos sobrecargas (uno para referencias lvalue y el segundo para los rvalue, ver §20.2.3/2):
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;
Sustituyendo int
, obtenemos:
int&& forward(int& t) noexcept;
int&& forward(int&& t) noexcept;
Y dado que nb
es lvalue, se elige la primera versión. Según el borrador estándar, el único efecto de forward
es static_cast<T&&>(t)
. Con T
siendo int
, obtenemos static_cast<int&&>(nb)
, es decir, obtenemos dos modelos exactamente iguales.
Ahora, si quieres lanzar lvalue a rvalue (para permitir el movimiento), usa solo std::move
, que es la forma idiomática de hacer esta conversión. std::forward
no está destinado a ser utilizado de esta manera.