【问题标题】:Why D doesn't allow object creation on stack?为什么 D 不允许在堆栈上创建对象?
【发布时间】:2016-02-27 05:22:17
【问题描述】:

考虑以下程序(查看现场演示here

import std.stdio;
class myclass
{
    public:
    int get_a()
    {
        return a;
    }
    private:
    int a=3;
}
int main()
{
    myclass m;  // It should be myclass m=new myclass();
    writefln("%d",m.get_a());   
    return 0;
}

C++ 支持自动(堆栈分配)和动态(堆分配)对象。但是为什么每个类对象都必须在 D 中动态分配呢?为什么 D 不支持堆栈分配的对象?

另一个令人惊讶的事情是ideone 给出了编译器错误:

prog.d(14): Error: null dereference in function _Dmain

但是当我在本地机器上的 dmd2 编译器上尝试它时,它给了我运行时错误而不是编译时错误。为什么?为什么这个程序的行为不同? 以下是我在本地机器上遇到的 dmd2 给出的错误。

object.Error@(0): Access Violation
----------------
0x00402056
0x00405F9B
0x00405EB1
0x00403D93
0x7651EE6C in BaseThreadInitThunk
0x7758377B in RtlInitializeExceptionChain
0x7758374E in RtlInitializeExceptionChain

【问题讨论】:

  • “所有变量都是引用”是相当常见的。在我熟悉的语言中,像 C 和 C++ 这样允许你用值语义定义类型的东西是例外,而不是规则。
  • D 确实允许您定义具有值语义的类型,就像结构而不是类一样。类总是通过引用来访问,但是你在哪里分配它引用的内存取决于你——包括在堆栈上。类总是通过引用的原因是这几乎总是你想要的方式 - 即使在 C++ 中 - 所以 D 遵循 Java 的领先地位并将其设为默认值。但是类并不是定义用户类型的唯一方法,所以不要忘记 struct!

标签: class object heap-memory d stack-memory


【解决方案1】:

D 确实允许将类放在堆栈上,请参阅 std.typecons.scoped

您在 ideone 上看到的 null 取消引用错误是因为编译器在优化期间发现了这个问题(ideone 似乎启用了优化)。尝试将 -O 开关添加到本地编译器调用中。

【讨论】:

  • 那么这个程序有什么问题。见这里:ideone.com/6p9isc。它编译失败。为什么编译器会报错?
  • import std.typecons;
  • 好的,谢谢。但是有什么用!构造函数之前的运算符? & 如果我写 myclass m=scoped !myclass(); & 调用 get_a() 成员函数会导致运行时错误?为什么?再次感谢
  • @PravasiMeet 你需要使用auto:auto m = scoped!myclass()。原因是scoped 是包含类内存的结构的模板,并且可以隐式转换为类。通过执行myclass m = scoped!myclass(),您丢弃了结构包装器,该包装器立即被释放。 ! 是模板实例化运算符(就像 <> 在 C++ 中一样)。
猜你喜欢
  • 2015-03-28
  • 2020-04-09
  • 1970-01-01
  • 2017-09-09
  • 2016-10-15
  • 2016-12-28
  • 2010-12-08
  • 1970-01-01
  • 2020-10-27
相关资源
最近更新 更多