2010-10-23 23 views
6

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

我很难过。任何想法,为什么这个打破? (Mac OS X 10.6.4上的DMD 2.049)。 预先感谢帮助n00b。

回答

5

你似乎在混合使用D类的C++类。

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

这意味着t设置为null,因为,null是指针的默认初始化程序 - 因此是错误。

编辑:你可以认为D Foo类作为C++的Foo*

如果你想把它分配到堆上,你可以尝试使用结构 - 他们也可以有方法,就像类一样。但是,他们不具有继承权。

+0

谢谢你的线索! :)(这是有道理的,也回答了为什么不需要对象解引用/成员操作符( - >) – anoncow 2010-10-23 22:25:23

+0

那么, - >操作符不会被要求 - 例如,在C中,编译器足够)实际上可以警告你,你使用的是错误的运算符。 以类似的方式,D的指针(比如说Foo *)不需要 - >,但可以使用点:'Foo * foo =​​; foo.bar = 5;' – 2010-10-23 22:27:32

+0

对不起,我指的不是动态分配的对象,而是基于堆栈的对象 – anoncow 2010-10-23 22:32:44

1

谢谢,Tim。

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


清分类实例在栈上

类实例通常被分配在垃圾收集堆中。但是,如果它们: 被分配为函数中的本地符号 使用新的 分配,请使用不带参数的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 

这(据说)分配堆栈上运行良好。 :)

再次感谢!

+2

然而,正如dsimcha在他的文章中指出的那样,范围计划被弃用,所以这不是一个好的长期解决方案。 – 2010-10-24 07:25:50

3

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

+0

哦,不!我也爱上了范围!我使用D2,所以我会阅读为什么,这已被弃用,悲伤。感谢您的结构建议 - C++的堆栈分配机制也遭受同样的困扰。 – anoncow 2010-10-24 23:56:48

+0

我相信它已被弃用,主要是因为它不安全。在栈上有一个类时,有可能在函数返回后引用该类并引用该引用不再有效。如果它在堆上,它将不会被垃圾收集,直到所有对它的引用都没有了,所以你不会有这个问题。 – 2010-10-25 16:22:25

+0

@anoncow:IIRC,**范围**被库解决方案所取代。 Smth像** Scoped!(YourType)var ** – 2010-11-02 07:01:30