D 中基于堆栈的对象实例化

发布于 2024-09-28 11:35:45 字数 881 浏览 0 评论 0原文

我正在学习 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

我被难住了。有什么想法为什么会破裂吗? (Mac OS X 10.6.4 上的 DMD 2.049)。 预先感谢您对 n00b 的帮助。

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风和你 2024-10-05 11:35:45

您似乎将 C++ 类与 D 类混淆了。

D 类总是通过引用传递(与 C++ 类不同),并且 PerformanceCounter t 不会在堆栈上分配该类,而只是分配一个指向该类的指针。

这意味着 t 设置为 null,因为 null 是指针的默认初始值设定项 - 因此会出现错误。

编辑:您可以将 D Foo 类视为 C++ 的 Foo*

如果您希望将其分配在堆上,您可以尝试使用结构 - 它们也可以有方法,就像类一样。然而,他们没有继承权。

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.

秋叶绚丽 2024-10-05 11:35:45

最明显的答案是使用struct。如果您使用的是无法控制的库或其他内容,并且堆分配是一个性能问题,则可以使用 std.typecons.scoped 功能来不安全地分配类实例堆栈。该实例仍然通过引用传递,如果其生命周期超过当前堆栈帧的生命周期,将导致未定义的行为。根据 anoncow 的回答,scope 关键字将起作用,但计划在 D2 中弃用。

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.

暖风昔人 2024-10-05 11:35:45

谢谢,蒂姆。

感谢您的回答,我能够在 http://www.digitalmars 找到以下内容。 com/d/2.0/memory.html


在堆栈上分配类实例

类实例通常在垃圾收集堆上分配。但是,如果他们:
被分配为函数中的局部符号
使用 new 进行分配
使用不带参数的 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 

This (据称) allocates on the stack 并且运行良好。 :)

再次感谢!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文