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);
}

只需要拒绝编译解引用无效,就可.
C++20中,拒绝编译A& a;,要求显式初化.
不一样,C++A&不能重绑定.而类引用则可以.
试试A* a;能否编译.

posted @   zjh6  阅读(45)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示