What's the correct way of creating an instance of class in D?
Tejas
notrealemail at gmail.com
Thu Nov 3 13:31:35 UTC 2022
On Thursday, 3 November 2022 at 04:41:14 UTC, Siarhei Siamashka
wrote:
> C++ code:
> ```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 code:
> ```D
> @safe:
> import std.stdio;
> class A {
> void foo() { writeln("foo"); }
> }
> void main() {
> auto a1 = new A;
> a1.foo(); // prints "foo"
> A a2;
> a2.foo(); // Segmentation fault
> }
> ```
>
> I didn't expect to see a segmentation fault in the code, which
> is a straightforward conversion from C++. And especially not
> with the use of the `@safe` attribute. What's going on here?
>
> ```
> $ ldc2 --version
> LDC - the LLVM D compiler (1.30.0):
> based on DMD v2.100.1 and LLVM 14.0.6
> built with LDC - the LLVM D compiler (1.30.0)
> Default target: x86_64-pc-linux-gnu
> ```
In D, all references and pointer types are default initialized to
`null` no matter what, so you always have to explicitly assign an
initial value if you dont want segfaults when dereferencing them
```d
import std.stdio:writeln;
void main(){
int* a;
writeln(*a); // program killed by signal 11
int* b = new int();
writeln(*b);
}
```
C++ initializes variable via the default constructor though,
because it is a value type, like D's `struct`s
```cpp
#include <iostream>
using namespace std;
class A{
public:
A(){
this -> a = new int(44);
}
int* a;
};
int main()
{
int* a;
cout << *a << "\n"; //prints any garbage value
A instance;
cout << *instance.a << "\n"; // always prints 44
return 0;
}
```
Use a pointer, and you'll get the same undesirable behaviour
```cpp
#include <iostream>
using namespace std;
class A{
public:
A(){
this -> a = new int(44);
}
int* a;
};
int main()
{
int* a;
cout << *a << "\n"; //prints any garbage value
A* instance;
cout << instance ->a << "\n"; // it's printing nothing for
some reason
return 0;
}
```
You do get an error message if you use reference though, which D
doesn't give even when using `@safe`
C++:
```cpp
#include <iostream>
using namespace std;
class A{
public:
A(){
this -> a = new int(44);
}
int* a;
};
int main()
{
int* a;
cout << *a << "\n"; //prints any garbage value
A& instance;
cout << instance.a << "\n"; // it's printing nothing for
some reason
return 0;
}
main.cpp: In function ‘int main()’:
main.cpp:28:8: error: ‘instance’ declared as reference but not
initialized
28 | A& instance;
| ^~~~~~~~
```
D with `@safe`:
```d
import std.stdio:writeln;
void main() @safe {
int* a;
writeln(*a); // still segfault
int* b = new int();
writeln(*b);
}
```
# 😖
More information about the Digitalmars-d-learn
mailing list