2017-04-17 80 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; 
    } 
}; 

這很容易變成一個模板推廣存儲

相關問題