On 6/5/22 11:43, Alain De Vos wrote:

> Does Foo(3) lives on the stack or the heap ?

It depends.

> there is a
> conversion.

Suche conversions are called "construction" in D.

> And what happes with
> Foo[3] arr = [one, two, Foo(3)];

Foo[3] is a static array. Static arrays are value types. Their elements normally do not live on heap:

void foo() {
  Foo[3] arr;    // On the stack
}

However, if Foo[3] were a member of something else

class C {
  int i;
  Foo[3] arr;
}

and if an object of C is constructed on heap

  auto c = new C();

then the Foo[3] member will also live on the heap alongside 'i'.

It could be the opposite: If the class object were emplaced on stack, then every member would we on the stack.

As you see, "on the stack" really depends.

Let's assume that your example is inside a function, i.e. the array is on the stack:

void foo() {
  Foo[3] arr = [one, two, Foo(3)];
}

Now all members of 'arr' on the stack. As 'one' and 'two' are lvalues, they are copied to arr[0] and arr[1]. But as Foo(3) is an rvalue, as Paul Backus said in the other message, that element is moved to arr[2].

So there are two copies and one move.

> Foo[]  arr=   [one, two, Foo(3)];

That one is different because Foo[] is a dynamic array that keeps its elements on the heap. That expression will allocate memory for at leasts 3 elements and to the same: Two copies and one move.

> and
> Foo x=Foo(3).dup()

If there were a dup() member function of Foo:

struct Foo {
  Foo dup() {
    return Foo(this.payload);
  }
}

In that case, as the returned object is an rvalue, it would be moved to 'x'. The returned object could be an lvalue:

struct Foo {
  Foo dup() {
    auto result = Foo(this.payload);
    // ...
    return result;
  }
}

In that case, the "named return value optimization" (NRVO) would be applied and the object would still be moved to 'x'.

Ali

Reply via email to