Stack-based object instantiation in D
I'm learning D, and am confused by an error I'm getting.
Consider the following:
module helloworld;
import std.stdio;
import std.perf;
ptrdiff_t main( string[] args )
{
auto t = new PerformanceCounter; //From managed h开发者_JS百科eap
//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()
Yields a perfectly respectable:
Hello, 32-bit world!
Elapsed time: 218 µs.
Now consider what happens when I attempt to initialize PerformanceCounter on the stack instead of using the managed heap:
//auto t = new PerformanceCounter; //From managed heap
PerformanceCounter t; //On the stack
Yields:
--- killed by signal 10
I'm stumped. Any thoughts as to why this breaks? (DMD 2.049 on Mac OS X 10.6.4). Thanks in advance for helping a n00b.
You seem to be mixing up C++ classes with D classes.
D classes are always passed by reference (unlike, say, C++ classes), and PerformanceCounter t
does not allocate the class on the stack, merely a pointer to it.
This means that t
is set to null
because, well, null
is the default initializer for pointers - hence the error.
EDIT: You can think of D Foo
class as a C++'s Foo*
.
If you want this to be allocated on the heap, you could try using structs instead - they can also have methods, just like classes. They do not, however, have inheritance.
The most obvious answer is to use a struct
. If you're using a library that you don't have control over or something and the heap allocations are a performance problem, you can use the std.typecons.scoped
functionality to unsafely allocate a class instance on the stack. The instance is still passed by reference and if its lifetime exceeds the lifetime of the current stack frame, undefined behavior will result. The scope
keyword as per anoncow's answer will work, but is scheduled for deprecation in D2.
Thanks, Tim.
Thanks to your answer, I was able to find the following at http://www.digitalmars.com/d/2.0/memory.html:
Allocating Class Instances On The Stack
Class instances are normally allocated on the garbage collected heap. However, if they: are allocated as local symbols in a function are allocated using new use new with no arguments (constructor arguments are allowed) have the scope storage class then they are allocated on the stack. This is more efficient than doing an allocate/free cycle on the instance. But be careful that any reference to the object does not survive the return of the function.
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
If the class has a destructor, then that destructor is guaranteed to be run when the class object goes out of scope, even if the scope is exited via an exception.
My code now reads
scope t = new PerformanceCounter(); //On the stack
This (allegedly) allocates on the stack and runs fine. :)
Thanks again!
精彩评论