2012-01-23 2 views
0

포인터를 함수에서 반환하면 해당 값을 개별적으로 액세스 할 수 있습니다. 그러나 루프가 포인터 변수의 값을 출력하는 데 사용되면 잘못된 값이 표시됩니다. 내가 실수하고있는 곳에서는 그것을 알아낼 수 없습니다.C++의 함수에서 포인터를 반환

#include <iostream> 
#include <conio.h> 

int *cal(int *, int*); 

using namespace std; 

int main() 
{ 
    int a[]={5,6,7,8,9}; 
    int b[]={0,3,5,2,1}; 
    int *c; 
    c=cal(a,b); 

    //Wrong outpur here 
    /*for(int i=0;i<5;i++) 
    { 
     cout<<*(c+i); 
    }*/ 

    //Correct output here 
    cout<<*(c+0); 
    cout<<*(c+1); 
    cout<<*(c+2); 
    cout<<*(c+3); 
    cout<<*(c+4); 

return 0; 
} 

int *cal(int *d, int *e) 
{ 
    int k[5]; 
    for(int j=0;j<5;j++) 
    { 
     *(k+j)=*(d+j)-*(e+j); 
    } 
    return k; 
} 
+10

컴파일러 경고를 켜고 읽습니다. –

+1

함수에서 포인터를 반환해야하는 경우는 거의 없습니다. 필자의 경험에 따르면 포인터를 반환해야 할 필요성은 결함이있는 프로그램 설계에서 비롯된 것입니다. 가장 자주 매개 변수 중 하나를 통해 결과를 반환하고 호출자가 데이터를 할당 할 위치를 고민하게합니다. – Lundin

+2

@Lundin 몇 가지 주목할만한 예외 (예 : 실패 할 수있는 조회 기능)가 있습니다. 반면에 매개 변수 중 하나를 통해 복귀하는 것은 절대적으로 필요한 경우에만 사용해야하며 프로파일 러에서 선택권이 없다고 말합니다. 대부분의 경우 올바른 해결책은 가치로 돌아가는 것입니다. 물론 C 스타일 배열을 사용하지 않는다는 것을 의미합니다 (하지만 일반적으로 좋은 추천입니다). –

답변

1

int k[5] 배열은 스택에 생성됩니다. 따라서 범위를 벗어나면 cal에서 복귀하여 파괴됩니다. 이 같은

void cal(int *d, int *e, int* k) 
{ 
    for(int j=0;j<5;j++) 
    { 
     *(k+j)=*(d+j)-*(e+j); 
    } 
} 

전화 cal : 당신은 출력 배열로 세 번째 매개 변수를 사용할 수

다른 사람들이 지적, 당신은 로컬 변수에 대한 포인터를 반환하고
int a[]={5,6,7,8,9}; 
int b[]={0,3,5,2,1}; 
int c[5]; 
cal (a, b, c); // after returning from cal, c will be populated with desired values 
+0

당신은'void' 리턴 함수에서 값을 리턴합니다! :) –

+0

@ another.anon.coward가 수정되었습니다. – Meysam

+0

아직 원시 포인터로 놀고 있으니 그럴 필요가 없습니다! – Johnsyweb

6

로컬 변수에 대한 포인터를 반환하고 있습니다.

k이 스택에 만들어집니다. cal()을 종료하면 스택이 풀리고 그 메모리는 해제됩니다. 나중에 메모리를 참조하면 정의되지 않은 동작이 발생합니다 (여기에서 아름답게 설명 됨 : https://stackoverflow.com/a/6445794/78845).

C++ 컴파일러는 경고해야하며 이러한 경고에 유의해야합니다. 그것은 여기에, 가치가 무엇인지에 대한

내가 ++ C에서 이것을 구현하는 것입니다 방법은 다음과 같습니다

#include <algorithm> 
#include <functional> 
#include <iostream> 
#include <iterator> 

int main() 
{ 
    int a[] = {5, 6, 7, 8, 9}; 
    int b[] = {0, 3, 5, 2, 1}; 
    int c[5]; 
    std::transform (a, a + 5, b, c, std::minus<int>()); 
    std::copy(c, c + 5, std::ostream_iterator<int>(std::cout, ", ")); 
} 

See it run!

+3

int k [5]가 삭제됩니다. – RvdK

+0

@PoweRoy : "파괴 될 수 있습니까?" 파괴된다는 보장은 없지, 그렇지? 그것은 분명히 불법적 인 접근입니다 ... –

+1

@ another.anon.coward : 파괴 될 것입니다, 그렇지 않으면 RAII가 작동하지 않을 것입니다. 다른 것들이 그 기억을 사용하는지 여부는 보장 될 수 없습니다. – Johnsyweb

0

정의되지 않은 동작. 그러나 실제 문제는 이며 배열을 반환해야하며 C 스타일 배열은 손상되었습니다. 배열을 std::vector<int>으로 바꾸고 포인터를 잊어 버리십시오 (값을 다루기 때문에) 이므로 코드가 작동합니다.

+0

'std :: vector' (또는 valarray)가 실제로 여기에 필요하지는 않지만 여러분 말이 맞습니다. 포인터가 필요 없습니다. – Johnsyweb

+0

@Johnsyweb 그의 구체적인 예를 들면,'std :: vector '이 명백하고 정확한 해결책이다. –

+0

C++ 11에서 initialser 목록을 사용하면 동의 하겠지만 "correct"는 주관적입니다. 예를 들어, [내 대답] (http://stackoverflow.com/a/8969311/78845)에 제공된 코드가 "올바른"mut는 표준 라이브러리의 컨테이너를 사용하지 않는다고 생각합니다. – Johnsyweb

관련 문제