2010-10-23 21 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