Quando eu tenho um loop e, dentro desse loop, crio uma nova variável de pilha (sem alocá-la no heap e com a variável declarada dentro do corpo do loop), é garantido que o destruidor desse objeto será chamado antes do início da próxima iteração ou poderá loop desenrolando pelo compilador mudar algo sobre isso?
c++
destructor
user1282931
fonte
fonte
Respostas:
De
n4800
:§6.3.3 Escopo do bloco :
§10.3.6 Destrutores :
§4.1.1 Máquina abstrata :
[Ênfase minha]
Então sim. Sua variável fica fora de escopo no final do loop (que é um bloco) e, portanto, seu destruidor é chamado na medida em que qualquer pessoa que observe o comportamento do programa possa perceber .
fonte
call
. Ou, se eles efetivamente (como regra) não fazem nada, pode não haver montagem para esses destruidores gerados.Sim. É mais fácil visualizar quando você considera os "blocos" nos quais declara uma variável, ou seja, entre qual par de chaves. O loop é um bloco em si e, quando atinge o colchete de fechamento, antes da próxima iteração, todos os destruidores de variáveis de armazenamento automático declaradas no loop são chamados.
Como regra geral, não pense no que o compilador otimizará, pois ainda precisa garantir o comportamento do seu programa, não importa o que ele faça para otimizá-lo. Nesse caso, o desenrolar do loop não mudará nada nesse sentido se isso acontecer.
fonte
[class.copy.elision]
for(...) X x{};
e ox
objeto será construído + destruído em cada iteração. Demonstração ao vivo . Uma seção padrão relevante é stmt.iter / 2 .[stmt.iter]
, é puramente equivalente (ênfase minha): "Se a subestação em uma declaração de iteração for uma declaração única e não uma declaração composta, é como se tivesse sido reescrita para ser uma declaração composta contendo a declaração original ". Em essência, com ou sem chaves para uma única declaração significa exatamente a mesma coisa e as chaves estão implícitas. Eu o omiti por clareza.O destruidor é chamado para todas as iterações. Assim, em alguns casos, é mais rápido declarar uma variável fora do loop em vez de no loop. Supondo o seguinte caso:
O destruidor não é chamado quando o loop é executado. Apenas substitui
temp
.Mas se você usa
std::string temp = arr[i]
o construtor e o destruidor, será chamado para cada iteração. Eu acho que isso adiciona um pouco de tempo de execução, caso você tenha um loop que é executado com muita frequência.fonte
O destruidor é chamado antes da próxima iteração
fonte
Obviamente, o dtor é chamado no final da iteração e o desenrolamento de loop não deve modificar esse comportamento, como qualquer outra otimização (uma otimização não deve modificar o comportamento do programa), exceto algum tipo de RVO e similar que pode eliminar algumas criações de objetos semanticamente espúrios .
fonte