2014-04-05 46 views
0

我對C++非常陌生,來自Fortran 90+和MATLAB背景。我一直在玩C++中的指針,並且偶然發現了一些我無法解釋的東西。 Google和Stack Overflow的搜索沒有真正解釋。在C++中返回指向具有普通函數和void函數的動態分配數組的指針

這是一個隨機的例子,我想到了,只是從亂搞,試圖瞭解C++如何工作。

實質上,我想要做的是在函數內分配一個動態數組,填充數組,然後在調用函數中返回一個指向數組的指針。如果我使用void函數將指針返回給數組,它不起作用。如果我把它作爲一個正常的函數返回,它就可以工作。我們分別稱這些案例1和案例2。

我已經把我的意思的例子:

#include <iostream> 
using namespace std; 

// Prototypes 
void populate(int rows, int cols, double* ptr_to_mat); 
double* populate_return(const int rows, const int cols); 

// Main function 
int main() 
{ 

    int rows, cols; 

    cout << "Number of rows: "; 
    cin >> rows; 
    cout << "Number of columns: "; 
    cin >> cols; 
    cout << endl; 

    double* ptr_to_mat; 

    populate(rows, cols, ptr_to_mat); 

    cout << endl << "OUTPUT IN main FROM populate" << endl; 

    for (int r = 0; r <= rows-1; r++) 
    for (int c = 0; c <= cols-1; c++) 
     cout << "mat(" << r << "," << c << ") = " << ptr_to_mat[c+cols*r] << endl; 

    cout << endl << endl; 

    ptr_to_mat = populate_return(rows, cols); 

    cout << endl << "OUTPUT IN main FROM populate_return" << endl; 

    for (int r = 0; r <= rows-1; r++) 
    for (int c = 0; c <= cols-1; c++) 
     cout << "mat(" << r << "," << c << ") = " << ptr_to_mat[c+cols*r] << endl; 


    delete [] ptr_to_mat; 

    return 0; 
} 

// Other functions 

// Return pointer by modifying argument -- CASE 1 
void populate(const int rows, const int cols, double* ptr_to_mat) 
{ 

    double* internal_mat = new double[rows*cols]; 

    cout << "INPUT IN populate" << endl; 

    for (int r = 0; r <= rows - 1; r++) 
    for (int c = 0; c <= cols - 1; c++) 
     { 
     cout << "mat(" << r << "," << c << ") = "; 
     cin >> internal_mat[c+cols*r]; 
     } 

    ptr_to_mat = internal_mat; 

    cout << endl << "OUTPUT IN populate" << endl; 

    for (int r = 0; r <= rows-1; r++) 
    for (int c = 0; c <= cols-1; c++) 
     cout << "mat(" << r << "," << c << ") = " << ptr_to_mat[c+cols*r] << endl; 

} 

// Return pointer using "return" -- CASE 2 
double* populate_return(const int rows, const int cols) 
{ 

    double* internal_mat = new double[rows*cols]; 

    cout << "INPUT IN populate_return" << endl; 

    for (int r = 0; r <= rows - 1; r++) 
    for (int c = 0; c <= cols - 1; c++) 
     { 
     cout << "mat(" << r << "," << c << ") = "; 
     cin >> internal_mat[c+cols*r]; 
     } 

    cout << endl << "OUTPUT IN populate_return" << endl; 

    for (int r = 0; r <= rows-1; r++) 
    for (int c = 0; c <= cols-1; c++) 
     cout << "mat(" << r << "," << c << ") = " << internal_mat[c+cols*r] << endl; 

    return internal_mat; 

} 

運行上面的代碼的結果如下:

Number of rows: 3 
Number of columns: 2 

CASE 1 
INPUT IN populate 
mat(0,0) = 1 
mat(0,1) = 2 
mat(1,0) = 3 
mat(1,1) = 4 
mat(2,0) = 5 
mat(2,1) = 6 

OUTPUT IN populate 
mat(0,0) = 1 
mat(0,1) = 2 
mat(1,0) = 3 
mat(1,1) = 4 
mat(2,0) = 5 
mat(2,1) = 6 

OUTPUT IN main FROM populate 
mat(0,0) = -1.72952e-41 
mat(0,1) = -2.77962e-42 
mat(1,0) = -2.77966e-42 
mat(1,1) = -2.7797e-42 
mat(2,0) = -6.02988e-42 
mat(2,1) = -2.77979e-42 


CASE 2 
INPUT IN populate_return 
mat(0,0) = 1 
mat(0,1) = 2 
mat(1,0) = 3 
mat(1,1) = 4 
mat(2,0) = 5 
mat(2,1) = 6 

OUTPUT IN populate_return 
mat(0,0) = 1 
mat(0,1) = 2 
mat(1,0) = 3 
mat(1,1) = 4 
mat(2,0) = 5 
mat(2,1) = 6 

OUTPUT IN main FROM populate_return 
mat(0,0) = 1 
mat(0,1) = 2 
mat(1,0) = 3 
mat(1,1) = 4 
mat(2,0) = 5 
mat(2,1) = 6 

我的假設是,它必須做當指針在調用函數中被分配時。因此,在情況2中,在將函數內的信息從內存釋放之前將其分配給左側,而在情況1中,在指針被分配到調用函數中之前釋放該內存,因爲分配發生在在右邊。

這聽起來似乎合理嗎?如果不是,案例2的工作原因是什麼,但案例1沒有?

如果我想在一個函數中分配多個動態數組並返回指向這些數組的指針,我必須使用void函數。在這種情況下可以做什麼/應該做什麼?

+2

使用'的std ::矢量' –

回答

4

void版本不起作用的原因是指針參數是按值傳遞的,所以函數有它自己的副本。爲了得到它的「工作」,你就必須通過一個指針引用:

void populate(int rows, int cols, double*& ptr_to_mat); 
//          ^

注意,在真正的代碼,你會傾向於使用管理自己的資源的std::vector或一些其他類型的,而不是將資源管理留給呼叫者。例如,

#include <vector> 

std::vector<double> populate(int rows, int cols); 
+0

啊,我明白了!非常感謝你解釋這一點。我還沒有達到通過參考傳遞參數。 (我一直想要使用矢量,但是我覺得從頭開始瞭解更多基本類型會有所幫助。) – dzoni

0

在C++參數中按值傳遞,所以在第一個實例中,您正在修改生成的指針的副本。使用指向指針的指針並通過引用來設置結果。

或者作爲更好的答案建議:使用參考。這不是C!

0

要正確設置指針在void功能,你需要按引用傳遞它:

void populate(const int rows, const int cols, double*& ptr_to_mat) { // ... 
相關問題