2017-04-17 631 views
-2

我在使用C++编写的代码时遇到问题。编译器向我发送错误C2440,我不知道为什么。这里是代码,问题出现在void main()区域,特别是在线路R = callocR[i] = calloc。感谢您的答案。错误C2440无法将void *转换为double **或double *

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <iostream> 
using namespace std; 

double F (double x); 
double G (double x); 
double P (double x); 

void romberg(double f(double), double a, double b, int n, double **R); 

double F (double x) 
{ 
    return (1.0/ (1.0 + x)); 
} 

double G (double x) 
{ 
    return (exp(x)); 
} 

double P (double x) 
{ 
    return (sqrt(x)); 
} 

void romberg(double f(double), double a, double b, int n, double **R) 
{ 
    int i, j, k; 
    double h, sum; 


    h = b - a; 
    R[0][0] = 0.5 * h * (f(a) + f(b)); 
    cout << " R[0][0] = "; 
    cin >> R[0][0]; 


    for (i = 1; i <= n; i++) 
    { 
    h *= 0.5; 
    sum = 0; 
    for (k = 1; k <= pow(2,i)-1; k+=2) 
    { 
     sum += f(a + k * h); 
    } 
    R[i][0] = 0.5 * R[i-1][0] + sum * h; 
    cout << "R[i][0] = "; 
    cin>>i, R[i][0]; 
    for (j = 1; j <= i; j++) 
    { 
     R[i][j] = R[i][j-1] + (R[i][j-1] - R[i-1][j-1])/(pow(4,j)-1); 
     cout << " R[i][j] = "; 
     cin>>i, j, R[i][j]; 
    } 
    } 
} 

void main() 
{ 
    int n = 10; 
    int i; 
    double **R; 
    double F(double), G(double), P(double); 

    R = calloc((n+1), sizeof(double *)); 
    for (i = 0; i <= n; i++) 
    R[i] = calloc((n+1), sizeof(double)); 
    cout<<"The first function is F(x) = 1/(1 + x)\n"; 
    romberg(F, 0.0, 2.0,3, R); 
    cout<<"The second function is G(x) = exp(x)\n"; 
    romberg(G,-1.0, 1.0, 4, R); 
    cout<<"The third function is P(x) = sqrt(x)\n"; 
    romberg(P,0.0, 1.0, 7, R); 
}  
+7

决不'无效main'的数据! 'int main'! – aschepler

+4

1.当你必须分配内存时使用'new' 2.你很少需要分配内存(使用标准容器,比如'std :: vector'或者使用智能指针)。 – crashmstr

+4

@crashmstr:不,不要使用'new',永远不要。 –

回答

-1

你的主要长相很奇怪:中

  • void main代替int main
  • double F(double), G(double), P(double); - ?!
  • 如果使用malloc/calloc/realloc,则必须在C++中投射返回的void指针。
  • 不要忘记删除分配的内存。

例如:

int main() 
{ 
    const int n = 10; 
    double **R; 

    R = new double*[n+1]; 
    for (int i = 0; i <= n; i++) 
     R[i] = new double[n+1]; 
    cout << "The first function is F(x) = 1/(1 + x)\n"; 
    romberg(F, 0.0, 2.0,3, R); 
    cout << "The second function is G(x) = exp(x)\n"; 
    romberg(G,-1.0, 1.0, 4, R); 
    cout<<"The third function is P(x) = sqrt(x)\n"; 
    romberg(P,0.0, 1.0, 7, R); 

    // free allocated memory 
    for (int i = 0; i <= n; i++) 
     delete[] R[i]; 
    delete[] R; 
} 

注意,循环,inits双打不将它们全部设置为0。

或者更好的使用std ::向量和更新您的其他代码使用它以及:

#include <vector> 
using namespace std; 

int main() 
{ 
    const int n = 10; 
    vector<vector<double> > R(n+1, vector<double>(n+1)); 
    cout << "The first function is F(x) = 1/(1 + x)\n"; 
    romberg(F, 0.0, 2.0,3, R); 
    cout << "The second function is G(x) = exp(x)\n"; 
    romberg(G,-1.0, 1.0, 4, R); 
    cout<<"The third function is P(x) = sqrt(x)\n"; 
    romberg(P,0.0, 1.0, 7, R); 
} 
+3

这是你的问题解释? _“你的主要看起来很奇怪。”_? –

+0

@ user4581301同意,这里使用矢量更好 – Pavel

+0

@Pavel'vector > R;' - 可能只是'vector > R(n + 1,std :: vector (n + 1) ));'。那么就不需要'for'循环。 – PaulMcKenzie

0

在C++中有一个vector容器(C++标准模板),其类似于一个数组与异常THA t将其自动处理的情况下,其自身的存储要求它的增长

你需要切换到RAII
例如:

从这:

double **R; 

    R = calloc((n+1), sizeof(double *)); 
    for (i = 0; i <= n; i++) 
    R[i] = calloc((n+1), sizeof(double)); 

要:

vector <vector <double> >R(n+1, vector<int>(n+1)); 

你不需要释放分配的内存,当向量超出范围时它将被释放。

的,你只需要改变的romberg到签名:

void romberg(double f(double), double a, double b, int n, vector <vector <double> >R) 

你也可以阅读有关RAII C++的概念。

PS:你得到的错误可以通过void *double *double **简单明确的铸造避免,但这样可能会导致你有更多的并发症,如内存泄漏等

1

为什么出错?

C++比C更严格的规则(而calloc是一个C函数),关于编译器在执行赋值时将执行什么类型的转换。 void *void *要求你告诉编译器,“是的,这看起来很愚蠢,很危险,但我知道我在做什么。”

为什么这是一个错误?

通过C和C++编程的年代来说,存在着很长时间的僵化的隐式转换。进行这种转换是一个错误,至少会让程序员在继续之前停下来思考它。

我该怎么办?

在这种情况下最合乎逻辑的简单的解决方案是

std::vector<std::vector<double>> descriptive_name_goes_here(n+1, std::vector<double>(n+1)); 

这将分配所有需要的存储空间,并且它全部设置为0。它管理其自己的存储器,包括删除,并根据需要调整大小。这几乎是火,忘了。

Documentation on std::vector

在此之后而来的各种智能指针,尤其是

std::unique_ptr<std::unique_ptr<double[]>[]> descriptive_name_goes_here = 
    std::make_unique<std::unique_ptr<double[]>[]>(n+1); 

for环路make_unique内部尺寸和分配所有分配的值,以0

unique_ptr处理内存管理,确保所引用的分配数据在不再被引用时被销毁。作为一个成员变量,unique_ptr可以传递或存储对象在容器中的痛苦在脖子上,因为如果一个unique_ptr可以复制,它不一定是唯一的,是吗? vector为你处理废话。

Documentation on std::unique_ptr

Documentation on std::make_unique

如果不知何故上述两个是不可能的,并且在2017年这应该是全人工限制或上遗留代码操作需要遗留编译的结果,使用

double ** descriptive_name_goes_here = new double*[n+1] 

for循环到new内部尺寸并将所有分配的值分配到0.

这个选项将所有的内存管理职责都放在编程人员身上,甚至编程之神偶尔会错过一个需要delete[]的情况。这也意味着程序员有责任支持Rules of Three and Five以确保任何包装类中的销毁,复制,分配和移动逻辑是正确的。

这是低级工作的绝对最后手段,如编写vector或智能指针。

在C++中唯一的地方是calloc会出现在奇怪的边缘情况下,坦率地说我现在想不出任何。这很可能没有。

随着选择的出路...

我可以建议做一个简单的矩阵类出一维数组的?数组数组的方法看起来不错,简单和优雅,并且通常具有完全可怕的高速缓存性能。这些阵列中的每一个(或向量的向量)都是由散布在存储器中的许多不同的内存块组成的。这使CPU更难预测下一步要去哪里以及要加载哪些数据。每当CPU必须停止并等待缓存被加载时,性能就会下降几个数量级。

#include <iostream> 
#include <vector> 

class Matrix 
{ 
private: 
    size_t rows, columns; 
    std::vector<double> matrix; 
public: 
    Matrix(size_t numrows, size_t numcols) : 
      rows(numrows), columns(numcols), matrix(rows * columns) 
    { 
    } 

    double & operator()(size_t row, size_t column) 
    { 
     // check bounds here 
     return matrix[row * columns + column]; // note 2D coordinates are flattened to 1D 
    } 

    double operator()(size_t row, size_t column) const 
    { 
     // check bounds here 
     return matrix[row * columns + column]; 
    } 

    size_t getRows() const 
    { 
     return rows; 
    } 
    size_t getColumns() const 
    { 
     return columns; 
    } 
}; 

这很容易变成一个模板推广存储

相关问题