digitalmars.D.learn - weird behave of Array?
- dmm (28/28) Jul 28 2019 import std.stdio : writefln;
- Adam D. Ruppe (14/15) Jul 28 2019 The array is passed by value here, so changes to its ptr and
- Adam D. Ruppe (2/2) Jul 28 2019 BTW If you want those length changes to be seen in the original,
- dmm (29/44) Jul 28 2019 So, d try to be smart, only make thing worse? the following code,
- FeepingCreature (22/23) Jul 29 2019 D is behaving exactly as it should here. You simply have a wrong
import std.stdio : writefln; void test(string str) { writefln("%d, %d", str.length, str.capacity); str.length = 10; writefln("%d, %d", str.length, str.capacity); } void main() { string str; str.reserve(1024); //str.length = str.capacity; writefln("%d, %d", str.length, str.capacity); test(str); writefln("%d, %d", str.length, str.capacity); } The output is: 0, 1358 0, 1358 10, 1358 0, 0 If I uncomment the line str.length = str.capacity; then the output is: 1358, 1358 1358, 1358 10, 0 1358, 1358 why?
Jul 28 2019
On Sunday, 28 July 2019 at 17:21:25 UTC, dmm wrote:test(str);The array is passed by value here, so changes to its ptr and length will not be seen outside the function. However, what goes *through* the pointer - which includes the contents and the capacity - will be seen. The runtime tries to minimize weird stuff by opting for making the capacity 0 if the array structure has been modified in a function (so of the length is changed, if it is appended, etc.), so then appends will not stomp over contents from two different locations. Since the memory pointed to is a shared resource it is conservative in not reusing it. You can read a bit more about this here https://dlang.org/articles/d-array-article.html#append-on (really the whole article might be good background).
Jul 28 2019
BTW If you want those length changes to be seen in the original, pass the array by ref to the functions doing the changes.
Jul 28 2019
On Sunday, 28 July 2019 at 17:45:16 UTC, Adam D. Ruppe wrote:On Sunday, 28 July 2019 at 17:21:25 UTC, dmm wrote:So, d try to be smart, only make thing worse? the following code, it keeping realloc when call reset. this won't happend in cpp if call vector.resize under capacity. import std.stdio : writefln; class Lexer { ubyte[] buf; this() { buf.reserve(1024); writefln("%x, %d, %d", buf.ptr, buf.length, buf.capacity); } void doSomething() { buf.length = 1024; } void reset() { buf.length = 0; writefln("%x, %d, %d", buf.ptr, buf.length, buf.capacity); } } void main() { Lexer l = new Lexer(); l.doSomething(); l.reset(); l.doSomething(); l.reset(); } BTW, why call reserve(1024) got capacity at 1358? isn't reserve(n) means capacity = length + n? how do you set capacity to 2 ^ n?test(str);The array is passed by value here, so changes to its ptr and length will not be seen outside the function. However, what goes *through* the pointer - which includes the contents and the capacity - will be seen. The runtime tries to minimize weird stuff by opting for making the capacity 0 if the array structure has been modified in a function (so of the length is changed, if it is appended, etc.), so then appends will not stomp over contents from two different locations. Since the memory pointed to is a shared resource it is conservative in not reusing it. You can read a bit more about this here https://dlang.org/articles/d-array-article.html#append-on (really the whole article might be good background).
Jul 28 2019
On Monday, 29 July 2019 at 05:58:21 UTC, dmm wrote:So, d try to be smart, only make thing worse?D is behaving exactly as it should here. You simply have a wrong model of what an array is in D. In C++, an array owns its memory. In D, an array is a thin wrapper around GC managed memory. As such, for instance, you can take a reference to an array field, then resize the array, and the original reference will still be valid and at its original value. To do what you want, use std.array.Appender, which owns its memory. import std.algorithm; import std.array; import std.range; import std.stdio; void main() { Appender!(int[]) app; 10.iota.each!(a => app.put(a)); writefln!"%s, %s"(app.data.ptr, app.data); app.shrinkTo(0); 10.iota.each!(a => app.put(a)); writefln!"%s, %s"(app.data.ptr, app.data); }
Jul 29 2019