从 D 中的结构体方法通过引用返回

发布于 2025-01-10 20:12:38 字数 1453 浏览 1 评论 0原文

我将从 C++ 开始我的 D 之旅。在 C++ 中,通过引用或值传递是相当明确的,但在 D 中,结构和类之间似乎有所不同。

我的问题是如何强制按参考退货?

我有一个简单的 XmlNode 类用于构建 Xml 树(这是我的 C++ 代码的提升):

import std.stdio; 

struct XmlNode
{
    string _name;
    string _data;
    XmlNode[] _children;

    this(string name, string data="")
    {
        _name = name;
        _data = data;
    }
    
    //Trying to return a reference to the added Node
    ref XmlNode addChild(string name,string data = "")
    {
        _children ~= XmlNode(name,data);
        return _children[$-1]; 
    }

    string toString(bool bPlain = true, string indent = "")
    {
        //Omitted for brevity
    }
}

这是测试代码:

int main()
{
    auto root = XmlNode("root");
    
    //Chained call
    root.addChild("Level 1").addChild("Level 2","42");

    //Call in two parts
    auto n = root.addChild("Level 1");
    n.addChild("Level 2","101"); //n seems to be a copy not a reference

    //Chained call
    root.addChild("Level 1").addChild("Level 2","999");

    writeln(root.toString(false));

    return 0;
}

给出以下输出:

root
  Level 1
    Level 2
      42
  Level 1
  Level 1
    Level 2
      999

正如您所看到的 addChild() 的“链接”使用 按预期执行。但是,如果我尝试将其分解为两个单独的调用,则只有第一个调用有效,而第二个调用似乎对第一个调用的副本进行操作,而不是引用。我乐观地向 addChild() 签名添加了一个 ref 限定符,但这似乎没有帮助。

一如既往,我将不胜感激任何建议(使用 DMD / Visual D / Visual Studio / Windows 10)。

I'm starting my journey in D from C++. In C++ passing by reference or value is quite explicit, but in D it seems to vary between structs and classes.

My question is how can I force a return by reference?

I have a simple XmlNode class for building Xml trees (which is a lift from my C++ code):

import std.stdio; 

struct XmlNode
{
    string _name;
    string _data;
    XmlNode[] _children;

    this(string name, string data="")
    {
        _name = name;
        _data = data;
    }
    
    //Trying to return a reference to the added Node
    ref XmlNode addChild(string name,string data = "")
    {
        _children ~= XmlNode(name,data);
        return _children[$-1]; 
    }

    string toString(bool bPlain = true, string indent = "")
    {
        //Omitted for brevity
    }
}

And here is the testing code:

int main()
{
    auto root = XmlNode("root");
    
    //Chained call
    root.addChild("Level 1").addChild("Level 2","42");

    //Call in two parts
    auto n = root.addChild("Level 1");
    n.addChild("Level 2","101"); //n seems to be a copy not a reference

    //Chained call
    root.addChild("Level 1").addChild("Level 2","999");

    writeln(root.toString(false));

    return 0;
}

which gives the following output:

root
  Level 1
    Level 2
      42
  Level 1
  Level 1
    Level 2
      999

As you can see the 'chained' use of addChild() performs as hoped. But if I try to break it up into two separate calls, only the first has an effect, and the second seems to operate on a copy of the first, not a reference. I optimistically added a ref qualifier to the addChild() signature, but that doesn't seem to help.

As ever, I'd be grateful for any advice (using DMD / Visual D / Visual Studio / Windows 10).

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

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

发布评论

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

评论(1

薆情海 2025-01-17 20:12:38
    auto n = root.addChild("Level 1");

在这里,虽然 addChild 返回一个引用,但它被分配给一个变量,从而取消引用并复制。相反,您可能想要:

    auto n = &root.addChild("Level 1");

请注意,D 没有引用变量,就像 C++ 中那样。变量只能是指针(尽管可以编写具有类似引用语义的包装模板)。

另请注意,在 XmlNode 的当前设计中,返回的引用仅在下次修改 _children 之前有效(因为这可能会导致重新分配,从而移动内容)到另一个地址,使任何现有的引用都过时)。这是一种常见的枪法,可以通过存储 XmlNode 的引用(或使其成为引用类型,即类)来避免,但代价是额外的取消引用和分配。

    auto n = root.addChild("Level 1");

Here, though addChild returns a reference, it is assigned to a variable, and thus dereferenced and copied. Instead, you probably want:

    auto n = &root.addChild("Level 1");

Note that D does not have reference variables, like in C++. Variables can be only pointers (though it's possible to write a wrapper template with reference-like semantics).

Also note that in the current design of XmlNode, the returned reference will only be valid until the next time _children is modified (as that may cause a reallocation and thus move the contents to another address, making any extant references outdated). It is a common footgun, which could be avoided by storing references of XmlNode (or making it a reference type i.e. a class), at the cost of extra dereferences and allocations.

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