D 结构体内存处理 - 从成员函数返回 `this`

发布于 2024-12-28 06:24:09 字数 1172 浏览 0 评论 0原文

uint ci = 0;

struct S
{
    uint i;

    this(int x)
    {
        i = ci;
        ci++;

        writeln("new: ", i);
    }

    this(this)
    {
        i = ci;
        ci++;

        writeln("copy ", i);
    }

    ~this()
    {
        writeln("del ", i);
    }

    S save1() // produces 2 copies in total
    {
        S s = this;
        return s;
    }

    auto save2() // produces 3 copies in total
    {
        S s = this;
        return s;
    }
}

Save1:

S s = S(1);
S t = S(1);

t = s.save1();

// Gives:
// new 0
// new 1
// copy 2
// del 1
// del 2
// del 0

Save2:

S s = S(1);
S t = S(1);

t = s.save2();

// Gives:
// new 0
// new 1
// copy 2
// copy 3
// del 3
// del 1
// del 3
// del 0

如您所见,save2() 变体永远不会“删除” i == 2 的结构。是否存在内存泄漏?如果我使用 auto 作为返回类型,我无法正确管理结构中的资源。

另外,如果 save() 只是返回 this 而没有临时值,我会得到:

S save()
{
    return this;
}

// new 0
// new 1
// copy 2
// del 1
// del 2
// del 2

这些是错误吗?如果我无法定义默认构造函数,我该如何进行正确的内存管理?这个设计决定背后的原因是什么?

我想将它用于前向范围,所以我不能使用class

uint ci = 0;

struct S
{
    uint i;

    this(int x)
    {
        i = ci;
        ci++;

        writeln("new: ", i);
    }

    this(this)
    {
        i = ci;
        ci++;

        writeln("copy ", i);
    }

    ~this()
    {
        writeln("del ", i);
    }

    S save1() // produces 2 copies in total
    {
        S s = this;
        return s;
    }

    auto save2() // produces 3 copies in total
    {
        S s = this;
        return s;
    }
}

Save1:

S s = S(1);
S t = S(1);

t = s.save1();

// Gives:
// new 0
// new 1
// copy 2
// del 1
// del 2
// del 0

Save2:

S s = S(1);
S t = S(1);

t = s.save2();

// Gives:
// new 0
// new 1
// copy 2
// copy 3
// del 3
// del 1
// del 3
// del 0

As you can see, the save2() variant never 'deletes' the struct with i == 2. Is it memory leaking? I cannot properly manage my resources in structs if I use auto as return type.

Also, if save() simply return this without the temporary, I get:

S save()
{
    return this;
}

// new 0
// new 1
// copy 2
// del 1
// del 2
// del 2

Are these bugs? How am I supposed to do proper memory management if I cannot define a default constructor? What is the reason behind this design decision?

I want to use it for a forward range, so I cannot use class.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拔了角的鹿 2025-01-04 06:24:09

对我来说看起来像一个错误。显然,save1save2 之间的唯一区别是后者使用 auto 返回而不是显式返回类型。除了一些不适用于此的极端情况外,这应该对 postblit 和 d'tor 调用没有影响。

Looks like a bug to me. Apparently the only difference between save1 and save2 is that the latter uses auto return instead of an explicit return type. Except in a few corner cases that don't apply here, this should have no effect on postblit and d'tor calls.

秋意浓 2025-01-04 06:24:09

无法使用 git dmd 重现错误代码部分:

new: 0
new: 1
copy 2
del 1
del 2
del 0
-
new: 0
new: 1
copy 2
copy 3
del 2
del 1
del 3
del 0
-
new: 0
new: 1
copy 2
del 1
del 2
del 0

我将剩余的 NRVO 问题提交为 http://d.puremagic.com/issues/show_bug.cgi?id=7353

Can't reproduce the wrong-code part with git dmd:

new: 0
new: 1
copy 2
del 1
del 2
del 0
-
new: 0
new: 1
copy 2
copy 3
del 2
del 1
del 3
del 0
-
new: 0
new: 1
copy 2
del 1
del 2
del 0

I filed the remaining NRVO issue as http://d.puremagic.com/issues/show_bug.cgi?id=7353

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文