Instanciação de objeto baseada em pilha em D
-
25-09-2019 - |
Pergunta
Estou aprendendo D e estou confuso com um erro que estou recebendo.
Considere o seguinte:
module helloworld;
import std.stdio;
import std.perf;
ptrdiff_t main( string[] args )
{
auto t = new PerformanceCounter; //From managed heap
//PerformanceCounter t; //On the stack
t.start();
writeln( "Hello, ", size_t.sizeof * 8, "-bit world!" );
t.stop();
writeln( "Elapsed time: ", t.microseconds, " \xb5s." );
return 0;
} //main()
Produz um perfeitamente respeitável:
Hello, 32-bit world!
Elapsed time: 218 µs.
Agora considere o que acontece quando tento inicializar o PerformanceCounter na pilha, em vez de usar a pilha gerenciada:
//auto t = new PerformanceCounter; //From managed heap
PerformanceCounter t; //On the stack
Rendimentos:
--- killed by signal 10
Estou perplexo. Alguma opinião sobre por que isso quebra? (DMD 2.049 no Mac OS X 10.6.4). Agradecemos antecipadamente por ajudar um N00B.
Solução
Você parece estar misturando aulas de C ++ com as classes D.
D aulas são sempre aprovado por referência (diferentemente, digamos, C ++ Classes) e PerformanceCounter t
não aloca a classe na pilha, apenas um ponteiro para ela.
Isso significa que t
está configurado para null
Porque, bem, null
é o inicializador padrão para ponteiros - daí o erro.
EDITAR: Você pode pensar em D Foo
classe como um C ++ Foo*
.
Se você deseja que isso seja alocado na pilha, você pode tentar usar estruturas - elas também podem ter métodos, assim como as aulas. Eles, no entanto, não têm herança.
Outras dicas
A resposta mais óbvia é usar um struct
. Se você está usando uma biblioteca que não tem controle ou algo assim e as alocações de heap são um problema de desempenho, você pode usar o std.typecons.scoped
Funcionalidade para alocar insegurosamente uma instância de classe na pilha. A instância ainda é passada por referência e, se sua vida útil exceder a vida útil do quadro da pilha atual, o comportamento indefinido resultará. o scope
A palavra -chave conforme a resposta de Anoncow funcionará, mas está programada para depreciação no D2.
Obrigado, Tim.
Graças à sua resposta, pude encontrar o seguinte em http://www.digitalmars.com/d/2.0/memory.html:
Alocando instâncias de classe na pilha
As instâncias de classe são normalmente alocadas na pilha coletada de lixo. No entanto, se eles: forem alocados como símbolos locais em uma função, são alocados usando o novo uso novo, sem argumentos (os argumentos do construtor são permitidos) têm a classe de armazenamento do escopo, eles são alocados na pilha. Isso é mais eficiente do que fazer um ciclo de alocação/livre na instância. Mas tenha cuidado para que qualquer referência ao objeto não sobreviva ao retorno da função.
class C { ... }
scope c = new C(); // c is allocated on the stack
scope c2 = new C(5); // allocated on stack
scope c3 = new(5) C(); // allocated by a custom allocator
Se a classe tiver um destruidor, é garantido que o destruidor seja executado quando o objeto da classe sair do escopo, mesmo que o escopo seja excitado por meio de uma exceção.
Meu código agora lê
scope t = new PerformanceCounter(); //On the stack
Isso (supostamente) aloca na pilha e funciona bem. :)
Obrigado novamente!