Pergunta

Gostaria de ter certeza de que minhas rotinas aproveitam (N)RVO sempre que possível.Além de analisar a desmontagem resultante, há algo que eu possa fazer ou verificar para ver se uma rotina está sendo compilada com (N)RVO?Neste ponto, estou mais interessado em MSVC e GCC.

Foi útil?

Solução

Não, na verdade não.

No entanto, você pode seguir as orientações ao escrever seu código.


Otimização de valor de retorno sem nome

Isso é praticamente acionado toda vez que você retorna um valor temporário, mesmo no modo de depuração.

return MyObject(....);

Otimização do valor de retorno nomeado

Isso é praticamente acionado toda vez que a função sempre retorna o mesmo objeto temporário:

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

  result.push(0);
  return result;
}

Você pode misturá-los, mas torna-se quase impossível para o compilador aplicar o RVO neste caso:

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

  return result;
}

Aqui, é provável que um retorno se beneficie da RVO e o outro não.E eu apostaria que o primeiro seria otimizado porque você ficaria preso se criasse especulativamente result no slot de retorno e de repente precisa pegar o if filial.Observe que simplesmente reordenar as instruções funciona:

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

  MyObject result;

  return result;
}

Portanto, a regra geral para a NRVO é que não deve haver return declaração entre a declaração de result e a return result; declaração que retorna qualquer coisa além de result em si.


Se você seguir isso, você acumulará as probabilidades a seu favor.E então é apenas uma questão de revisão de código.

E você também facilita a leitura do seu código, já que não declara variáveis ​​antes de saber que realmente precisa delas!

Outras dicas

Você pode adicionar métodos de depuração ao destruidor:

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

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

Se o destruidor for chamado, provavelmente o RVO não foi aplicado.

As maneiras possíveis em que posso pensar são:

  1. Implementar um mecanismo de contagem de referências em sua classe que monitore o número de instâncias criadas por meio da classe, algo parecido com um shared_ptr faz, desta forma você pode detectar cópias extras de sua classe sendo criadas e removidas se a elisão de cópia não estiver acontecendo.

  2. Você poderia simplesmente colocar rastreamentos de depuração no construtor e destruidor de cópia para sua classe; se a elisão de cópia não estiver acontecendo, você verá muitos rastreamentos de depuração sucessivos do construtor e do destruidor de cópias.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top