【问题标题】:Cannot pass by reference in D languageD语言不能通过引用传递
【发布时间】:2013-11-29 23:05:36
【问题描述】:

我在类 testclass 中有一个构造函数

@safe public nothrow this(ref Socket socket) {
    // Inside class modulename.classname
    this.socket = socket;
}

然而,当我在我的 main 方法中初始化这种类型的对象时,我得到了一些编译错误。

void main() {
    auto variablename = new modulename.classname(
        cast(Socket) new TcpSocket() // main.d line 5
    );
}

错误:

main.d(5): Error: constructor testmodule.testclass.this (ref 
Socket socket) is not callable using argument types (Socket)
main.d(5): Error: no constructor for testclass

为什么我不能通过引用传递套接字?

【问题讨论】:

  • 通过 ref 传递 socket 在这种情况下是没有意义的,因为你从来没有分配给它。 Socket 类型已经是一个 ref(隐藏的指针),因此通过 ref 传递它最终成为对引用的引用(例如,指向指针的指针)。

标签: reference pass-by-reference d


【解决方案1】:

你不应该需要通过 ref 传递类

默认情况下,类是通过引用来保存的(以避免继承时的切片问题),所以无论如何你都只传递一个指针

您的代码中的问题是 cast(Socket) new TcpSocket() 是一个无法分配的右值,因此无法通过 ref 传递

【讨论】:

    【解决方案2】:

    接受的答案在陈述中不正确:

    您不需要通过 ref 传递课程
    类默认通过引用保存

    类是引用类型,但对类的引用按值作为方法参数传递。这只有在您修改引用所指的内容时才会发挥作用。

    例如,修改类成员时的通常情况适用于任何一种方式:

    import std.stdio;
    
    class K {
        int i;   
    }
    
    void main()
    {
        auto k = new K();
        k.i = 3;
        NonRef(k);
        writeln(k.i);    // Writes 5
        
        k.i = 3;
        ByRef(k);
        writeln(k.i);    // Writes 5
    }
    
    void NonRef(K k) {
        k.i = 5;
    }
    
    void ByRef(ref K k) {
        k.i = 5;
    }
    

    但是,考虑一下:

    import std.stdio;
    
    class K {
        int i;   
    }
    
    void main()
    {
        auto k = new K();
        k.i = 3;
        NonRef(k);
        writeln(k.i);    // Writes 3 !
        
        k.i = 3;
        ByRef(k);
        writeln(k.i);    // Writes 0 !
    }
    
    void NonRef(K k) {
        k = new K();
    }
    
    void ByRef(ref K k) {
        k = new K();
    }
    

    至于你的问题,在这个答案的时候,D 仍然不支持通过 ref 传递的 RValues。我推测这与编译器不知道将 ref 值应用回什么有关。正如您在答案中所做的那样,通过创建一个临时变量可以轻松克服这一问题。

    【讨论】:

    • 好吧,当您考虑接受的答案时,您会意识到它说“您不应该...”,您将其误解为“您不能...”。您需要多长时间通过引用传递引用?我 - 从来没有。
    • Dejane,答案在术语上不够精确,所以我想更正它。不需要的意思是“不需要”。如果我们想要恢复这种效果,我们实际上“确实需要”。同样的问题在 C# 中不断出现,因为这也是它在那里的工作方式。所以我认为澄清这一点很重要。
    【解决方案3】:

    我通过在构造函数调用之外初始化 Socket 解决了这个问题。我不确定这是一个错误,还是故意这样的语言。

    void main() {
        auto socket = cast(Socket) new TcpSocket();
        auto variablename = new modulename.classname(
            socket
        );
    }
    

    【讨论】:

    • D 语言目前不允许 D 右值引用 - 或者至少我认为不允许。进行了一些讨论,但我认为当前的后备箱中还没有任何东西。
    猜你喜欢
    • 2011-09-16
    • 2015-03-12
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2023-03-03
    • 2019-08-22
    • 1970-01-01
    • 2018-11-18
    相关资源
    最近更新 更多