2014-04-05 1 views
0

저는 Fortran 90+ 및 MATLAB 배경에서 나온 C++을 매우 새로 도입했습니다. 나는 C++로 포인터를 가지고 놀았으며, 나는 설명 할 수없는 것을 발견했다. 구글과 스택 오버 플로우에서의 검색은 실제로 설명을하지 못했다.C++에서 일반 함수와 void 함수를 사용하여 동적으로 할당 된 배열에 대한 포인터 반환

이것은 임의적 인 예입니다. C++의 작동 방식을 이해하려고 노력하고 있습니다.

본질적으로, 내가하려는 것은 함수 내에 동적 배열을 할당하고, 배열을 채우고, 호출 함수에서 배열에 대한 포인터를 반환하는 것입니다. 배열에 포인터를 반환하는 void 함수를 사용하는 경우 작동하지 않습니다. 내가 반환과 함께 정상적인 기능으로 그것을한다면, 그것은 잘 작동합니다. 이 사례 1과 사례 2를 각각 호출 해 봅시다.

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 

내 가설은 함께 할 수 있다는 것입니다 : 위의 코드를 실행 한 결과는 다음과 같다

#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; 

} 

:

나는 무슨 말인지의 예를 함께 넣었습니다 호출 함수에서 포인터가 할당 될 때. 따라서 케이스 2에서는 함수 내의 정보가 메모리에서 할당 해제되기 전에 왼쪽에 할당되지만, 케이스 1에서는 할당이 발생하기 때문에 호출 함수에서 포인터가 할당되기 전에 메모리가 할당 해제됩니다. 오른쪽.

그럴듯한가요? 그렇지 않은 경우 케이스 2가 작동하는 이유는 무엇입니까? 케이스 1은 그렇지 않습니까?

함수에 둘 이상의 동적 배열을 할당하고 해당 배열에 대한 포인터를 반환하려면 void 함수를 사용해야합니다. 이 경우 무엇을 할 수 있습니까 /해야합니까?

+2

사용'표준 : : 벡터 ' –

답변

4

void 버전이 작동하지 않는 이유는 포인터 매개 변수가 값으로 전달되므로 해당 함수에 자체 복사본이 있기 때문입니다. 실제 코드에서 당신은 자신의 자원을 관리하는 std::vector 또는 다른 유형을 사용하기보다는 경향이 있다는

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

참고 : "작업"을 얻으려면, 당신은 포인터에 대한 참조를 전달해야 할 것입니다 발신자에게 자원 관리를 맡기십시오. 예 :

#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) { // ... 
관련 문제