Scope & Structs

Richard (Rikki) Andrew Cattermole richard at cattermole.co.nz
Fri Oct 18 07:43:47 UTC 2024


On 13/10/2024 6:12 PM, Salih Dincer wrote:
> On Saturday, 12 October 2024 at 13:11:52 UTC, Richard (Rikki) Andrew 
> Cattermole wrote:
>> You are not wrong, when it is a struct, it is being heap allocated.
> 
> Sorry for prolonging the topic. I am very curious about your answers 
> along with your patience...
> 
> Can we say that structs are in the stack (LIFO) as long as we do not use 
> the new operator? Also, should using scope in structures cause a change? 
> I never seen it does! However, there is no incompatibility here: Whether 
> it is a class or a struct, when you use the new operator, the first run 
> constructor becomes the first run destructor with FIFO logic.
> 
> You can reverse this situation with scope (but only in classes). By 
> reverse I don't mean LIFO! In fact, the correct expression is that when 
> you are done with the object, it is removed.
> 
> Thanks, SDB at 79

Sorry for not replying sooner, COVID has not been a fun virus for my 
mind to have.

When a variable is declared with a struct that needs cleanup, it 
effectively rewrites the following statements into a try finally:

```d
void main()
{
	S s = 0;
	try
	{
		if (true)
			return 0;
	}
	finally
		s.~this();
	return 0;
}
```

There are simplifications of this, without the need for the try finally, 
but we can ignore it for the purposes of this explanation.

The same can be seen with a class that was allocated on the stack:

```d
void main()
{
	scope C c = new C;
	try
	{
		if (true)
			return 0;
	}
	finally
		delete c;
	return 0;
}
```

Nested:

```d
void main()
{
	scope C c = new C;
	try
	{
		S s = 0;
		try
		{
			if (true)
				return 0;
		}
		finally
			s.~this();
	}
	finally
		delete c; // aggregate dtor is called
	return 0;
}
```

How nesting destroys fields:

```d
class C : Object
{
	S s;
	scope ~this() // user dtor
	{
	}
	scope ~this() // field dtor
	{
		this.s.~this();
	}
	scope ~this() // aggregate dtor
	{
		// user dtor , field dtor
		this.~this() , this.~this();
	}
}
```

This should cover the ordering on the stack. If you have any further 
questions about it please ask.

---------------------------------------------

 > Also, should using scope in structures cause a change?
 > I never seen it does!

The scope attribute in a declaration body such as a struct, class or 
union applies to the method, for its this pointer. It does not apply to 
the fields.

Generally speaking, scope should not be on a type or field declaration.

Good:

```d
struct S {
	int fields;

	private shared int* thing;

export @safe nothrow @nogc:

	this() scope {}

	void method1() scope {}

	scope { // ok
		void method2() {}
	}

scope: // no indication at function that it is applied, not great
	void method3() {}
}
```

Bad:

```d
struct S {
export @safe nothrow @nogc scope:

	int fields;

	this() {}

	void method() {}
}

shared scope struct S {
export @safe nothrow @nogc:

	int fields;

	this() {}

	void method() {}
}
```



More information about the Digitalmars-d-learn mailing list