0
点赞
收藏
分享

微信扫一扫

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;​​能否编译.


举报

相关推荐

0 条评论