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.

Foi útil?

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!

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