Managing malloced memory
Mike Parker
aldacron at gmail.com
Mon Oct 11 14:03:28 UTC 2021
On Monday, 11 October 2021 at 10:53:15 UTC, anon wrote:
>> S makeS(int x)
>> {
>> return S(x); // no destructor called here.
>> }
>>
>> void main()
>> {
>> foo(S(1)); // no destructor called for this rvalue
>> auto s = makeS(1);
>> // destructor for s called here.
>> foo(makeS(1)); // only one destructor called at the end of
>> foo
>> }
>> ```
> Is there any reference for exactly how these rules apply, or is
> this implementation defined? The
> [specification](https://dlang.org/spec/struct.html#struct-destructor) says that destructors are called when objects go out of scope. Your examples seem to suggest that this is untrue in some cases.
For example, in `makeS` the initializer combined with the return
triggers an optimization (return value optimization, or RVO))
that elides a copy of the struct, meaning there's nothing to
destroy at the end of `makeS`. The destruction will occur in the
scope into which the instance is moved.
Any time you have a named instance, like `S s = S(1)`, you can
pretty much guarantee its destructor will be called. An exception
is when `s` is returned immediately after the initialization,
then NRVO (named return value optimization) can kick in to elide
the copy and, therefore, the destruction again happens at the end
of the scope into which the instance is moved.
Play around with a struct destructor that prints a message and
you'll get a feel for when destructors are and aren't called.
Like Steve said, it's once per copy. Sometimes you end up with
temporaries that are destroyed, sometimes you don't depending on
compiler optimizations.
More information about the Digitalmars-d-learn
mailing list