天天看点

d中正确创建类实例

​​原文​​

//c++
#include <iostream>
class A {
public:
  void foo() { std::cout << "foo" << std::endl; }
};
int main() {
  auto a1 = new A;
  a1->foo(); // prints "foo"
  A a2;
  a2.foo();  // prints "foo"
  delete a1;
}
//D 版:

@safe:
import std.stdio;
class A {
  void foo() { writeln("foo"); }
}
void main() {
  auto a1 = new A;
  a1.foo(); // 打印 "foo"
  A a2;
  a2.foo(); // 段错误.
}      

未用​

​@safe​

​,怎么回事?

A a2;
a2.foo();
//约==C++的
A *a2 = NULL;
a2->foo();      

正确.​

​D​

​​中的类就像​

​Java​

​​中的类.​

​a2​

​​是​

​引用​

​​.另一方面,​

​构​

​​是确保与​

​C++​

​​中一样的​

​值型​

​.

在D中,所有​

​引用和指针​

​​都默认​

​初化​

​​为​

​无效(null)​

​​,因此,如果在解引用时,不想​

​段错误​

​​,则必须​

​显式​

​​分配​

​初值​

​.

import std.stdio:writeln;


void main(){
    int* a;
    writeln(*a); // 11信号干掉它.
    int* b = new int();
    writeln(*b);
}      

​C++​

​​因为与​

​D构​

​​一样,是​

​值类型​

​​,通过​

​默认​

​​构造器​

​初化​

​变量.

#include <iostream>

using namespace std;


class A{
    public:
    A(){
        this -> a = new int(44);
    }
    int* a;
};

int main()
{
    int* a;

    cout << *a << "\n"; //打印垃圾值

    A instance;
    cout << *instance.a  << "\n"; // 总是打印44
    return 0;
}      

使用​

​指针​

​​,会得到​

​同样​

​不良行为.

#include <iostream>

using namespace std;


class A{
    public:
    A(){
        this -> a = new int(44);
    }
    int* a;
};

int main()
{
    int* a;

    cout << *a << "\n"; //打印垃圾值

    A* instance;
    cout << instance ->a  << "\n"; 
//未打印
    return 0;
}      

但是,如果使用​

​引用​

​​,则会收到一条​

​错误消息​

​​,而​

​D​

​​即使用​

​@安全​

​也不会提示.

#include <iostream>

using namespace std;


class A{
    public:
    A(){
        this -> a = new int(44);
    }
    int* a;
};

int main()
{
    int* a;

    cout << *a << "\n"; //打印垃圾值

    A& instance;
    cout << instance.a  << "\n";
// 未打印.
    return 0;
}//要报错.      

​D的安全​

​:

import std.stdio:writeln;


void main() @safe {
    int* a;
    writeln(*a); // 段错误
    int* b = new int();
    writeln(*b);
}      

在D中,在堆上​

​分配​

​​所有​

​类实例​

​​,​

​类变量​

​​是引用它们.按​

​局部​

​​变量声明​

​A​

​​的​

​实例​

​​,会初化为​

​空引用(无效null)​

​​,因此在其上​

​调用​

​​方法会正确地​

​段错误​

​​.

可在栈上分配​​

​类实例​

​:

scope Object o = new Object;      
import std.typecons : scoped;
import std.stdio;

class C {
    int i;
}

void main() {
    // 或这样:
    // auto c = scoped!C();

    // 或这样
    scope c = new C();

    writeln("如果关闭地址值,则对象在栈中");
    writeln(&c);
    writeln(&c.i);
}