【问题标题】:What does `*&` in a function declaration mean?函数声明中的 `*&` 是什么意思?
【发布时间】:2009-09-15 12:48:08
【问题描述】:

我按照这个思路写了一个函数:

void myFunc(myStruct *&out) {
    out = new myStruct;
    out->field1 = 1;
    out->field2 = 2;
}

现在在调用函数中,我可能会这样写:

myStruct *data;
myFunc(data);

这将填充data 中的所有字段。如果我在声明中省略了“&”,这将不起作用。 (或者更确切地说,它只会在函数中本地工作,但不会改变调用者中的任何内容)

有人可以向我解释一下这个“*&”实际上是做什么的吗?它看起来很奇怪,我无法理解它。

【问题讨论】:

    标签: c++ pointers reference


    【解决方案1】:

    C++ 变量声明中的 & 符号表示它是 reference

    它恰好是对指针的引用,它解释了您所看到的语义;被调用函数可以改变调用上下文中的指针,因为它有一个对它的引用。

    所以,重申一下,这里的“有效符号”不是*&,这种组合本身并不意味着很多。 *myStruct * 类型的一部分,即“指向myStruct”的指针,而& 使其成为引用,因此您可以将其读作“out 是对指向指针的引用” myStruct"。

    在我看来,最初的程序员可以将其写成:

    void myFunc(myStruct * &out)
    

    甚至(不是我个人的风格,但当然仍然有效):

    void myFunc(myStruct* &out)
    

    当然,关于风格还有很多其他的看法。 :)

    【讨论】:

    • "...像任何其他 & 在 C++ 中的名称之前..." 有点草率。 (当这样说时,它也可能是地址运算符。)不过,很好的答案。 +1
    • @sbi:同意,我改变了它......不过现在它可能有点自我参照。
    • 现在好多了,我希望。 :) 有点学术,因为 Adriaan 的回答已被接受。
    • @unwind:我认为改进投票最多的答案是一个非常好的主意,即使 OP 已经放弃了这个问题。毕竟 SO 是可搜索的,下一个遇到这个问题的程序员会很感激你的回答。
    • @sbi:我当然同意。我宁愿正确也不愿接受。
    【解决方案2】:

    在 C 和 C++ 中,& 表示引用调用;您允许函数更改变量。 在这种情况下,您的变量是指向 myStruct 类型的指针。在这种情况下,该函数分配一个新的内存块并将其分配给您的指针“数据”。

    在过去(比如 K&R)这必须通过传递一个指针来完成,在这种情况下是一个指向指针的指针或 **。引用运算符允许更易读的代码和更强的类型检查。

    【讨论】:

      【解决方案3】:

      可能值得解释一下为什么不是&*,而是反过来。原因是,声明是递归构建的,所以对指针的引用就像

      & out // reference to ...
      * (& out) // reference to pointer
      

      括号被删除,因为它们是多余的,但它们可以帮助您了解模式。 (要了解为什么它们是多余的,想象一下表达式中的内容,您会注意到首先获取地址,然后取消引用 - 这是我们想要的顺序,括号不会改变)。如果你改变顺序,你会得到

      * out // pointer to ...
      & (* out) // pointer to reference
      

      指向引用的指针不合法。这就是为什么顺序是*&,意思是“引用指针”。

      【讨论】:

        【解决方案4】:

        这看起来你正在重新实现一个构造函数!

        为什么不直接创建合适的构造函数?
        请注意,在 C++ 中,结构就像一个类(它可以有一个构造函数)。

        struct myStruct
        {
            myStruct()
                :field1(1)
                ,field2(2)
            {}
        };
        
        myStruct*  data1 = new myStruct;
        
        // or Preferably use a smart pointer
        std::auto_ptr<myStruct>   data2(new myStruct);
        
        // or a normal object
        myStruct    data3;
        

        【讨论】:

        • 确实,我正在重新实现一个构造函数。谢谢你的提示!
        【解决方案5】:

        在 C++ 中,它是对指针的引用,有点等价于 C 中指向指针的指针,因此函数的参数是可赋值的。

        【讨论】:

          【解决方案6】:

          就像其他人所说的那样,& 表示您正在将实际变量的引用引用到函数中,而不是它的副本。这意味着对函数中的变量所做的任何修改都会影响原始变量。当您传递一个指针时,这可能会变得特别令人困惑,该指针已经是对其他东西的引用。如果您的函数签名看起来像这样

          void myFunc(myStruct *out);
          

          会发生的情况是,您的函数将被传递一个指针副本以供使用。这意味着指针将指向同一事物,但将是不同的变量。在这里,对*out 的任何修改(即out 指向的内容)将是永久性的,但对out(指针本身)所做的更改将仅适用于myFunc 内部。有了这样的签名

          void myFunc(myStruct *&out);
          

          您声明该函数将引用原始指针。现在对指针变量out所做的任何更改都会影响传入的原始指针。

          话虽如此,行

          out = new myStruct;
          

          正在修改指针变量out 而不是*out。无论out 曾经指向什么,它仍然存在并且很好,但是现在已经在堆上创建了一个新的myStruct 实例,并且out 已被修改为指向它。

          【讨论】:

            【解决方案7】:

            与 C++ 中的大多数数据类型一样,您可以从右到左阅读它,这样会很有意义。

            myStruct *&out
            

            out 是对指向 myStruct 对象的指针 (*) 的引用 (&amp;)。它必须是一个引用,因为您想更改 out 指向的内容(在本例中为 new myStruct)。

            【讨论】:

              【解决方案8】:

              我的类 *&我的对象

              这里的 MyObject 是对 MyClass 的一个指针的引用。所以调用 myFunction(MyClass *&MyObject) 是通过引用调用,我们可以改变 MyObject 是对指针的引用。但是如果我们执行 myFunction(MyClass *MyObject) 我们不能更改 MyObject,因为它是按值调用的,它只会将地址复制到一个临时变量中,这样我们就可以更改 MyObject 指向的值而不是 MyObject 的值。

              所以在这种情况下,作者首先为 out 分配一个新值,这就是为什么需要通过引用调用。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-09-03
                • 2022-06-19
                • 1970-01-01
                • 1970-01-01
                • 2011-09-24
                相关资源
                最近更新 更多