【问题标题】:Function reference and pointer函数引用和指针
【发布时间】:2021-09-08 03:51:58
【问题描述】:

我正在尝试使用编码良好的库为正态分布创建累积密度函数 (CDF)。该库的实施与我的问题无关。所以我只在这里添加了接口。

void cumnor ( double *arg, double *result, double *ccum );

现在,我的成员函数接口:

double N(const double& x) const;

实施:

double EuropeanOption::N(const double& x) const
{ // cumulative density functions (CDF)
    
    double cum, ccum;
    cumnor(&x, &cum, &ccum);

    return cum; 
}

所以我的函数基本上取CDF中积分(x)的上限并返回值P。

但编译器会抛出以下内容:

EuropeanOption.cpp: In member function ‘double EuropeanOption::N(const double&) const’:
EuropeanOption.cpp:82:9: error: invalid conversion from ‘const double*’ to ‘double*’ [-fpermissive]
  cumnor(&x, &cum, &ccum);
         ^~
In file included from EuropeanOption.hpp:3:0,
                 from EuropeanOption.cpp:3:
cdflib.hpp:60:6: note:   initializing argument 1 of ‘void cumnor(double*, double*, double*)’
 void cumnor ( double *arg, double *result, double *ccum );
      ^~~~~~

我的问题是我应该如何编写这个函数?我只想称它为 N(d1)。我不太明白为什么我不能在这里传递 &x 作为第一个参数。

【问题讨论】:

    标签: c++ pointers reference


    【解决方案1】:

    我不太明白为什么我不能在这里传递 &x 作为第一个参数。

    &x 传递给期望double* 作为参数类型的函数是不正确的。如果允许,它会让被调用函数更改x 的值,即const

    要解决问题,请创建一个函数局部变量并使用它。

    double EuropeanOption::N(const double& x) const
    { // cumulative density functions (CDF)
        
        double temp_x = x;
        double cum, ccum;
        cumnor(&temp_x, &cum, &ccum);
    
        return cum; 
    }
    

    作为一项额外改进,在调用cumnor 之前将cumccum 初始化为零。

    double EuropeanOption::N(const double& x) const
    { // cumulative density functions (CDF)
        
        double temp_x = x;
        double cum = 0, ccum = 0;
        cumnor(&temp_x, &cum, &ccum);
    
        return cum; 
    }
    
    

    【讨论】:

    • 非常感谢。这个变量副本效果很好。在使用 cum 和 ccum 之前有什么特别的理由来初始化它们吗?从编程实践方面来讲。谢谢
    • @YehuiHe "在使用 cum 和 ccum 之前有什么特别的原因吗?" - 如果cumnor() 没有设置它们,即失败。但如果它总是设置它们,那么事先初始化它们是多余的。
    • @RemyLebeau 我看到了 cumnor() 的代码。它总是设置它们。我总是在函数调用之前初始化变量,以防导致未初始化变量的值不可预测。
    【解决方案2】:

    您不能将&x 传递给cumnor(),因为x 是对const double 的引用,但cumnor() 需要一个指向非const double 的指针。作为非常量,cumnor() permission 可以更改给定的double 的值,如果它愿意的话。如果实际情况并非如此,那么它应该采用指向const double 的指针:

    void cumnor ( const double *arg, double *result, double *ccum );
    

    另一方面,根本没有充分的理由通过 const 引用 传递double。理想情况下,它应该按值传递,例如:

    void cumnor ( double arg, double *result, double *ccum );
    ...
    double EuropeanOption::N(double x) const
    { // cumulative density functions (CDF)
        
        double cum, ccum;
        cumnor(x, &cum, &ccum);
    
        return cum; 
    }
    

    但是,如果对cumnor() 进行更改不是一个选项(即,因为您无权更改库的界面),那么您需要更改N() 而不是传递cumnor() 想要的.例如,通过使用一个本地的double 变量,它是x 指向的double副本,例如:

    double EuropeanOption::N(const double& x) const
    { // cumulative density functions (CDF)
        
        double x_copied = x, cum, ccum;
        cumnor(&x_copied, &cum, &ccum);
    
        return cum; 
    }
    

    或者,如果您确定知道cumnor() 不会改变double 的值,您可以改用const_cast(不过,我相信人们会劝阻您)从使用这个),例如:

    double EuropeanOption::N(const double& x) const
    { // cumulative density functions (CDF)
        
        double cum, ccum;
        cumnor(const_cast<double*>(&x), &cum, &ccum);
    
        return cum; 
    }
    

    或者,如果您只是通过值而不是指针来获取x,那么将&amp;x 传递给cumnor() 可以正常工作,同时保持N() 不能改变调用者的double 变量的语义,例如:

    double EuropeanOption::N(double x) const
    { // cumulative density functions (CDF)
        
        double cum, ccum;
        cumnor(&x, &cum, &ccum);
    
        return cum; 
    }
    

    【讨论】:

    • 非常感谢。更改库不是一种选择,制作副本似乎不是我的风格。我选择按值传递 x。很好的解释。指针和引用对我来说是很难的概念。 :)
    猜你喜欢
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 2017-05-30
    • 2011-12-13
    • 1970-01-01
    • 2018-09-12
    • 2011-04-26
    相关资源
    最近更新 更多