digitalmars.D - why std.stdio.File is a struct?
- lumpyzhu (2/2) Oct 19 2016 std.stdio.File has reference counter inside,
- Jonathan M Davis via Digitalmars-d (19/21) Oct 20 2016 By using a struct with a reference count, you get deterministic destruct...
- Kagamin (6/11) Oct 20 2016 They could be reference counted classes if it played well with
- ketmar (4/6) Oct 20 2016 and even if you need, most of the time it is better to write
- Chris (6/12) Oct 21 2016 I use a few classes, but mainly to structure the program (some
- lumpyzhu (16/40) Oct 22 2016 thanks..
- Jonathan M Davis via Digitalmars-d (22/36) Oct 22 2016 You can mark a parameter as ref, and you get something similar to C++'s ...
- Namespace (4/28) Oct 23 2016 There is still the way to use an universal rvalue => lvalue
std.stdio.File has reference counter inside, why not std.stdio.File is class?
Oct 19 2016
On Thursday, October 20, 2016 06:59:12 lumpyzhu via Digitalmars-d wrote:std.stdio.File has reference counter inside, why not std.stdio.File is class?By using a struct with a reference count, you get deterministic destruction, and the file will be closed as soon as the reference count hits zero. If it were a class, then it would only be closed when the GC happened to collect the memory, and there's no guarantee that it will _ever_ collect the memory (e.g. the GC normally only runs when you call new, so if you never allocate memory again after allocating the File, then the GC will never collect it even if nothing refers to it anymore). User-defined types that manage system resources are pretty much always better off as structs so that they can have deterministic destruction. Java requiring you to do it manually, because there's no guarantee that the finalizers for their file classes will ever run, and you risk the resource never being released until the program terminates, which can be a big problem. We'd have the same problem if we used a class for std.stdio.File, whereas using a struct works great. In general, in D, if you don't need inheritance and polymorphism, you probably shouldn't be using a class. - Jonathan M Davis
Oct 20 2016
On Thursday, 20 October 2016 at 07:40:05 UTC, Jonathan M Davis wrote:User-defined types that manage system resources are pretty much always better off as structs so that they can have deterministic destruction.They could be reference counted classes if it played well with the language.In general, in D, if you don't need inheritance and polymorphism, you probably shouldn't be using a class.Streams genuinely need polymorphism though because they can present a wide variety of devices.
Oct 20 2016
On Thursday, 20 October 2016 at 07:40:05 UTC, Jonathan M Davis wrote:In general, in D, if you don't need inheritance and polymorphism, you probably shouldn't be using a class.and even if you need, most of the time it is better to write templated free functions with constraints instead. ;-)
Oct 20 2016
On Thursday, 20 October 2016 at 12:24:14 UTC, ketmar wrote:On Thursday, 20 October 2016 at 07:40:05 UTC, Jonathan M Davis wrote:I use a few classes, but mainly to structure the program (some are singletons). The rest are all structs and functions/templated functions. On hindsight, I would probably not go down that path again. Better avoid the class system altogether, ask the British ;)In general, in D, if you don't need inheritance and polymorphism, you probably shouldn't be using a class.and even if you need, most of the time it is better to write templated free functions with constraints instead. ;-)
Oct 21 2016
On Thursday, 20 October 2016 at 07:40:05 UTC, Jonathan M Davis wrote:On Thursday, October 20, 2016 06:59:12 lumpyzhu via Digitalmars-d wrote:thanks.. but structs are copy by value, In C++, I can use reference to avoid value-copy, ------------------------------------------ class MyClass {....}; void myFunc(const MyClass& a, MyClass& b) {...}; { MyClass object; myFunc(object); // f will destroyed here. } ------------------------------------------ in c++, I know where the object is destroyed.. but how to convert this c++ code to d?std.stdio.File has reference counter inside, why not std.stdio.File is class?By using a struct with a reference count, you get deterministic destruction, and the file will be closed as soon as the reference count hits zero. If it were a class, then it would only be closed when the GC happened to collect the memory, and there's no guarantee that it will _ever_ collect the memory (e.g. the GC normally only runs when you call new, so if you never allocate memory again after allocating the File, then the GC will never collect it even if nothing refers to it anymore). User-defined types that manage system resources are pretty much always better off as structs so that they can have with stuff like closing files, essentially requiring you to do it manually, because there's no guarantee that the finalizers for their file classes will ever run, and you risk the resource never being released until the program terminates, which can be a big problem. We'd have the same problem if we used a class for std.stdio.File, whereas using a struct works great. In general, in D, if you don't need inheritance and polymorphism, you probably shouldn't be using a class. - Jonathan M Davis
Oct 22 2016
On Sunday, October 23, 2016 06:13:29 lumpyzhu via Digitalmars-d wrote:thanks.. but structs are copy by value, In C++, I can use reference to avoid value-copy, ------------------------------------------ class MyClass {....}; void myFunc(const MyClass& a, MyClass& b) {...}; { MyClass object; myFunc(object); // f will destroyed here. } ------------------------------------------ in c++, I know where the object is destroyed.. but how to convert this c++ code to d?You can mark a parameter as ref, and you get something similar to C++'s &, except that it only works on parameters, return types, and the variable for the current element in a foreach loop (you can't declare local variables that are ref), and ref parameters only ever accept lvalues, even if they're const. e.g. void foo(ref int i) {...} ref int bar() { return _i; } foreach(i, ref e; arr) {...} I think that most D code just passes structs around without worrying about the cost of copying unless the struct is particularly large or profiling has shown that copying it is too expensive. For a lot of stuff, it simply isn't a problem. And when it is, there's ref, or the struct can be put on the heap and passed around by pointer. But because we don't have an equivalent for const& that accepts rvalues, using ref simply to avoid copying can get annoying. So, it doesn't make much sense to do it unless it's actually necessary (whereas a lot of C++ code does it just in case it matters). There is talk of possibly adding a way to pass rvalues by ref in D, in which case, you would get something similar to C++ const&, but there are problems caused by C++'s approach that we don't want in D, and D's const is enough more restrictive than C++ const that whatever we do can't be tied to const. - Jonathan M Davis
Oct 22 2016
On Sunday, 23 October 2016 at 06:36:21 UTC, Jonathan M Davis wrote:You can mark a parameter as ref, and you get something similar to C++'s &, except that it only works on parameters, return types, and the variable for the current element in a foreach loop (you can't declare local variables that are ref), and ref parameters only ever accept lvalues, even if they're const. e.g. void foo(ref int i) {...} ref int bar() { return _i; } foreach(i, ref e; arr) {...} I think that most D code just passes structs around without worrying about the cost of copying unless the struct is particularly large or profiling has shown that copying it is too expensive. For a lot of stuff, it simply isn't a problem. And when it is, there's ref, or the struct can be put on the heap and passed around by pointer. But because we don't have an equivalent for const& that accepts rvalues, using ref simply to avoid copying can get annoying. So, it doesn't make much sense to do it unless it's actually necessary (whereas a lot of C++ code does it just in case it matters). There is talk of possibly adding a way to pass rvalues by ref in D, in which case, you would get something similar to C++ const&, but there are problems caused by C++'s approach that we don't want in D, and D's const is enough more restrictive than C++ const that whatever we do can't be tied to const. - Jonathan M DavisThere is still the way to use an universal rvalue => lvalue conversion function.
Oct 23 2016