【问题标题】:Question on Function Declaration关于函数声明的问题
【发布时间】:2010-08-30 14:35:49
【问题描述】:

给定两个代码示例,哪个是首选?在第一个中,返回变量被定义为局部变量。在第二个中,返回变量由调用者传递。您是否允许定义一个函数并返回一个传递给它的变量?我这只是其中一个的偏好吗?有性能差异吗?

float compute_diam(float circumference, float pi) {

float rval;

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

rval = circumference / pi;

return rval;
}

float compute_diam(float circumference, float pi, float rval) {

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

rval = circumference / pi;

return rval;
}

谢谢

【问题讨论】:

    标签: c function syntax coding-style


    【解决方案1】:

    我认为在这两种情况下,第一种更好,原因如下 1. 由于您通过值传递变量时的性能,它会在您声明 rval 的地方创建一次,并且当您将该 rval 传递给函数时,将第一个 rval 的值复制到第二个。

    如果你想以这种方式传递变量,则通过引用传递它

    void main()
    {
    float result;
    compute_diam(2.1, 3.14, &result);
     } 
    void compute_diam(float circumference, float pi, float* rval) {
    
    /* Circumference = pi * diameter, so
       diameter = circumference / pi */
    
    *rval = circumference / pi;
    
    
    }
    

    函数变量result完成后会保存diameter的值。

    【讨论】:

    • 在你的例子中,你不是通过引用传递rval,而是一个指向它的指针,虽然同样正确,但它是不同的。
    • 传递指针是传递引用。 C 中没有引用之类的东西。
    【解决方案2】:

    有时您可能希望传递变量的引用,然后将其填充为适当的值或返回代码。

    但是第二个定义没有任何意义。

    int foo()
    {
    int a=6;
    return a; // This is ok
    }
    
    int foo(int a)
    {
    a = 5;
    return a; // Calling function cant access the value 5 in the parameter 
    //passed, it has to hold it in another variable
    }
    
    void foo(int* a)
    {
    *a=5;
    return; // Here you can return and still access the value 5 in the calling 
    //function with the variable passed to it
    }
    

    因此我假设您想在第一种和第三种方法之间做出决定,我会说它的具体实现。如果您想传递一系列返回值(读取数组、结构),您可以使用第二个。

    【讨论】:

    • 和@Ahsan一样,你不是通过引用传递a...它是一个指向int的指针...
    • #Cedric - 在 C 中,传递引用是通过传递变量(指针)的地址并在函数内取消引用该地址以读取或写入实际变量来模拟的。这将被称为“C 风格的传递引用”。 - 来源stackoverflow.com/questions/2229498/passing-by-reference-in-c
    【解决方案3】:

    我更喜欢第一个,因为第二个没有任何意义。第二个你没有传入引用或指向 rval 的指针,所以你只是分配给一个局部变量(就像你在第一个中一样,但它的创建方式不同),然后将该变量的副本返回给调用者.请注意,您没有将值保存在传递给函数的 rval 中,而是将其保存在由函数通过参数列表创建的本地 rval 中。

    即使第二个示例传递了对 rval 的引用,我仍然更喜欢第一个示例,因为 rval 是常规类型,并且可以轻松有效地复制。我也发现:

    float diameter = compute_diam(circumference, pi);
    

    比以下内容更具可读性和简洁性:

    float diameter = 0;
    compute_diam(circumference, pi, diameter);
    

    如果您将数据放入大型对象/结构中,那么将引用传递给函数会更有意义。编译器多次可以优化与导致返回值副本的函数关联的副本,因此我可能会保留选项 1,直到您通过使用探查器发现它需要优化为类似于 2nd版本。

    此外,您可以从参数列表中删除 pi 并在函数体内创建一个 static const float PI = 3.14xxxx;

    【讨论】:

      【解决方案4】:

      通常,将返回值存储在作为参数传递的地址的唯一原因是:

      • 您需要返回多个值。
      • 您需要返回一个结构。
      • 需要使用函数的返回值来返回错误。
      • 该函数旨在修改其中一个参数。

      如果您查看标准 C 库或大多数 API,您会发现很少有返回值实例存储在作为参数传递的地址中。

      【讨论】:

        【解决方案5】:

        这让我觉得你不明白什么是返回值或如何给函数提供参数。

        在第二个示例中,您不会修改在函数调用时提供的rval,而是修改它的副本。然后您将返回 rval 的值。

        那么你的第二个例子是“错误的”(从逻辑的角度来看)。

        你想要做的是

        void compute_diam(float circumference, float pi, float& rval) {
        
        /* Circumference = pi * diameter, so
        diameter = circumference / pi */
        
        rval = circumference / pi;
        
        }
        

        编辑:更正,上面只是C++,在C中你会做以下

        void compute_diam(float circumference, float pi, float* rval) {
        
        /* Circumference = pi * diameter, so
        diameter = circumference / pi */
        
        *rval = circumference / pi;
        
        }
        

        rval 由引用给出,函数不返回任何内容(void)。

        但在那种简单的情况下应该避免这种情况,如果函数返回值,界面会更清晰。

        编辑: 为了让您相信您的第二个示例格式不正确,请考虑以下几点:

        float my_result = compute_diam(2.0, 3.14, '为什么要放在这里?my_result ?')

        【讨论】:

        • 请注意,C 中没有引用,因此您必须使用指针而不是 float&
        猜你喜欢
        • 2022-01-23
        • 1970-01-01
        • 2014-09-05
        • 1970-01-01
        • 2013-02-25
        • 1970-01-01
        • 2020-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多