Thread overview | |||||
---|---|---|---|---|---|
|
December 17, 2012 does 'auto ref T' copy or not if passed rvalue | ||||
---|---|---|---|---|
| ||||
For the code below, S is never copied even though a version of the function resolving to void x.foo!(x.S).foo(x.S) is called. How is this possible? Is it an optimization? I figure if I call a function that takes its parameter by value, there should be a copy. Thanks Dan --------------- Output ----------------- T: abc is ref T: xyz is not ref --------------- Code ----------------- import std.stdio; struct S { char c[]; this(this) {writeln("Copying S\n");} } void foo(T)(auto ref T t) { writeln("T: ", t.c, (__traits(isRef, t) ? " is ref " : " is not ref ")); } void main() { S s = { ['a','b','c'] }; foo(s); foo(S(['x', 'y', 'z'])); } -------------- nm -C x | ddmangle | grep foo 0000000000477ab4 W void x.foo!(x.S).foo(ref x.S) 00000000004783fc W void x.foo!(x.S).foo(x.S) |
December 17, 2012 Re: does 'auto ref T' copy or not if passed rvalue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dan | On 12/17/12, Dan <dbdavidson@yahoo.com> wrote:
> Is it an optimization?
I think it is. You can get rid of auto ref and you'll see it still doesn't copy for the second case, e.g. change signature to:
void foo(S t);
And only this call copies:
foo(s);
This one doesn't copy:
foo(S(['x', 'y', 'z']));
The optimization makes sense since this object doesn't exist outside the foo function.
Btw, you might want to use `char[] c;`, not `char c[];` since that syntax will eventually be deprecated.
|
December 17, 2012 Re: does 'auto ref T' copy or not if passed rvalue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dan | On Monday, December 17, 2012 06:21:38 PM Dan wrote:
> For the code below, S is never copied even though a version of
> the function resolving to void x.foo!(x.S).foo(x.S) is called.
> How is this possible?
> Is it an optimization? I figure if I call a function that takes
> its parameter by value, there should be a copy.
>
> Thanks
> Dan
>
> --------------- Output -----------------
> T: abc is ref
> T: xyz is not ref
> --------------- Code -----------------
> import std.stdio;
>
> struct S {
> char c[];
> this(this) {writeln("Copying S\n");}
> }
>
> void foo(T)(auto ref T t) {
> writeln("T: ", t.c, (__traits(isRef, t) ? " is ref " : " is not
> ref "));
> }
>
> void main() {
> S s = { ['a','b','c'] };
> foo(s);
> foo(S(['x', 'y', 'z']));
> }
> --------------
>
> nm -C x | ddmangle | grep foo
> 0000000000477ab4 W void x.foo!(x.S).foo(ref x.S)
> 00000000004783fc W void x.foo!(x.S).foo(x.S)
struct literals are currently incorrectly considered to be lvalues (I think that that may finally be fixed on master though), so the lvalue version will be called for them right now. Once that's fixed, I don't know for sure, but what it will probably do is call the rvalue version but do a move, so no copy will be made.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation