Реализация объектов в стеке в D

Я изучаю D, и меня смущает ошибка, которую я получаю.

Учтите следующее:

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()

Выходит вполне респектабельно:

Hello, 32-bit world!
Elapsed time: 218 µs.

Теперь рассмотрим, что происходит, когда я пытаюсь инициализировать PerformanceCounter в стеке вместо использования управляемой кучи:

 //auto t = new PerformanceCounter;  //From managed heap
 PerformanceCounter t;               //On the stack

Урожайность:

--- killed by signal 10

Я в тупике. Любые мысли о том, почему это ломается? (DMD 2.049 в Mac OS X 10.6.4). Заранее спасибо за помощь n00b.

3 ответа

Решение

Вы, кажется, смешиваете классы C++ с классами D.

D классы всегда передаются по ссылке (в отличие, скажем, от классов C++), и PerformanceCounter t не размещает класс в стеке, просто указывает на него.

Это означает, что t установлен в null потому что, ну, null является инициализатором по умолчанию для указателей - следовательно, ошибка.

РЕДАКТИРОВАТЬ: Вы можете думать о D Foo класс как C++ Foo*,

Если вы хотите, чтобы это было размещено в куче, вы можете попробовать вместо этого использовать структуры - они также могут иметь методы, как классы. Однако они не имеют наследства.

Наиболее очевидный ответ заключается в использовании struct, Если вы используете библиотеку, которую вы не можете контролировать или что-то в этом роде, и выделение кучи является проблемой производительности, вы можете использовать std.typecons.scoped функциональность для небезопасного размещения экземпляра класса в стеке. Экземпляр по-прежнему передается по ссылке, и если его время жизни превышает время жизни текущего стекового кадра, результатом будет неопределенное поведение. scope ключевое слово в соответствии с ответом anoncow будет работать, но в D2 запланировано устаревшее.

Спасибо, Тим.

Благодаря вашему ответу мне удалось найти следующее по адресу http://www.digitalmars.com/d/2.0/memory.html:


Распределение экземпляров класса на стеке

Экземпляры класса обычно размещаются в куче мусора. Однако, если они: выделены как локальные символы в функции, они распределяются с использованием new use new без аргументов (аргументы конструктора разрешены) имеют класс хранения области действия, тогда они размещаются в стеке. Это более эффективно, чем выполнение цикла выделения / освобождения для экземпляра. Но будьте осторожны, чтобы любая ссылка на объект не переживала возвращение функции.

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

Если у класса есть деструктор, то этот деструктор гарантированно будет запущен, когда объект класса выйдет из области видимости, даже если область действия выходит из исключения.


Мой код теперь читает

scope t = new PerformanceCounter();  //On the stack 

Это (предположительно) размещается в стеке и работает нормально.:)

Еще раз спасибо!

Другие вопросы по тегам