함수에서 배열을 반환


212

int arr[5]함수에 전달 되는 배열 이 있습니다 fillarr(int arr[]).

int fillarr(int arr[])
{
    for(...);
    return arr;
}
  1. 해당 배열을 어떻게 반환합니까?
  2. 어떻게 사용합니까? 포인터에 어떻게 액세스 할 수 있습니까?

46
이 문맥에서 엄격하게 말하면 배열이 참조로 전달되므로 배열을 반환 할 필요가 없으므로 'arr'내부의 요소에 대한 변경 사항은 함수 외부에서 볼 수 있습니다.
BuggerMe

12
배열 반환은 체인 기능에 편리합니다.
seand

5
스택에 배열을 만들고 포인터를 반환하는 실수를하지 않는 한.
detly

2
@ismail : 배열이 동적으로 할당되지 않으면 새 배열을 반환 할 수 없습니다. 이 경우을 사용하십시오 std::vector.
GManNickG

4
@ BuggerMe : 배열은 참조로 전달 되지 않습니다 (훨씬 더 재미있는 구문으로 요청하지 않는 한) 코드에서 배열 첫 번째 요소에 대한 포인터로 붕괴 되고 함수로 전달됩니다. 5함수 시그니처는 컴파일러에 의해 폐기된다.
David Rodríguez-dribeas

답변:


204

이 경우 배열 변수 arr는 실제로 암시 적 변환을 통해 메모리에서 배열 블록의 시작을 가리키는 포인터로 취급 될 수도 있습니다. 사용중인이 구문은 다음과 같습니다.

int fillarr(int arr[])

일종의 구문 설탕입니다. 실제로 이것을 이것으로 바꿀 수 있으며 여전히 작동합니다.

int fillarr(int* arr)

같은 의미에서 함수에서 반환하려는 것은 실제로 배열의 첫 번째 요소에 대한 포인터입니다.

int* fillarr(int arr[])

그리고 일반적인 배열처럼 계속 사용할 수 있습니다.

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}

45
명확히하기 위해 "클래식 C ++ 문"은 거짓입니다. 배열은 포인터가 아닙니다.
GManNickG

25
a [i] == * (a + i) 규칙 기억
seand

8
@ 브렌트 내쉬 배열은 배열입니다. 배열의 시작에 대한 포인터는 포인터입니다. 컴파일러에는 일부 상황에서 번역을 수행하는 구문 설탕이 있습니다. array그리고 &array많은 경우에 교환 할 수있다.
Carl Norum

20
@ 브렌트 : 아니요. 배열은 자체 유형이며 특별한 종류의 포인터가 아닙니다. 의 유형 a에가 int a[10]있다 int[10]. 당신이 말할 수있는 것은 배열이 첫 번째 요소에 대한 포인터로 "부패"입니다. (이것은 암시적인 배열에서 포인터로의 변환입니다.) 그러면 당신의 대답은 나의 행을 따라 갈 것입니다. 배열, 배열 간 포인터 변환 및 포인터를 구별하기 위해 답변을 편집하면 동일한 핵심 정보가 있고 첫 번째이기 때문에 답변을 삭제합니다.
GManNickG

8
@seand a [i] == * (a + sizeof (a) * i) 규칙 기억
Amir

114

C ++ 함수는 C 스타일 배열을 값으로 반환 할 수 없습니다. 가장 가까운 것은 포인터를 반환하는 것입니다. 또한 인수 목록의 배열 유형은 단순히 포인터로 변환됩니다.

int *fillarr( int arr[] ) { // arr "decays" to type int *
    return arr;
}

인수와 리턴에 배열 참조를 사용하여이를 개선하여 붕괴를 방지 할 수 있습니다.

int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
    return arr;
}

Boost 또는 C ++ 11을 사용하면 참조 기준 전달은 선택 사항이며 구문은 덜 구부러집니다.

array< int, 5 > &fillarr( array< int, 5 > &arr ) {
    return arr; // "array" being boost::array or std::array
}

array템플릿은 단순히 생성 struct은 객체 지향 의미를 적용 아직 배열의 원래 단순성을 유지할 수 있도록 포함하는 C 스타일 배열을.


4
배열을 참조로 전달할 수있는 방법의 예를 제공하는 +1 그러나 참조로 배열을 반환 할 수 없다는 점에서 잘못되었습니다. 이를 달성하는 가장 간단한 구문은 typedef를 사용하는 것입니다. typedef int array[5]; array& foo();그러나 다음과 같이 작성해야한다면 typedef가 필요하지 않습니다 . int (&foo())[5] { static int a[5] = {}; return a; }질문의 예는 다음과 같습니다 int (&foo( int (&a)[5] ))[5] { return a; }. 간단하지 않습니까?
David Rodríguez-dribeas

@David : 고마워요. Comedef 메시지에서 typetype error: function returning array is not allowed이 아닌 구문으로 외부 parens를 제외하면 발생 하는 잘못된 인상을 받았습니다 . 운 좋게도 오늘 나는 또 다른 질문에 대한 오른쪽 왼쪽 규칙을 검토하고 당신이 그것이 가능하다고 말하는 것을 보았을 때…
Potatoswatter

1
chubsdad 의 대답 은 표준에서 올바른 인용문을 가지고 있습니다. 배열을 반환 할 수는 없지만 배열에 대한 참조 또는 포인터를 반환 할 수 있습니다. 배열은 복사 할 수없고 (유형) 복사 할 수없는 반환 될 수 없으며, 구문이 존재하면 컴파일러는 인수를 포인터로 변환합니다.
David Rodríguez-dribeas

3
@David : 그렇습니다. 이 페이지는 기이하게 길어지고 있습니다. 너무 많은 사람들이 자발적으로 너무 많은 사소한 함수를 작성하여 한곳에서 배열을 반환하지 마십시오.
Potatoswatter

@Potatoswatter 저는 cpp를 처음 사용합니다. 두 번째 코드 스 니펫을 자세히 설명 할 수 있습니까? 이해를 돕기 위해 부분으로 나눌 수 없습니다.
KPMG

23

C ++ 11에서는을 반환 할 수 있습니다 std::array.

#include <array>
using namespace std;

array<int, 5> fillarr(int arr[])
{
    array<int, 5> arr2;
    for(int i=0; i<5; ++i) {
        arr2[i]=arr[i]*2;
    }
    return arr2;
}

2
인용 OP :(...) you can consider the array returned arr2, totally another array (...)
cubuspl42

22

$ 8.3.5 / 8 상태-

"함수는 리턴 형 타입의 포인터 나 함수를 가질 수 있지만 리턴 형 타입의 포인터 나 함수를 가지지 않아야한다.

int (&fn1(int (&arr)[5]))[5]{     // declare fn1 as returning refernce to array
   return arr;
}

int *fn2(int arr[]){              // declare fn2 as returning pointer to array
   return arr;
}


int main(){
   int buf[5];
   fn1(buf);
   fn2(buf);
}

7
두 번째 함수는 int배열이 아닌에 대한 포인터를 반환합니다 .
GManNickG

다시 함수 내에서 실제 배열이 업데이트 될 때 왜 유형을 반환합니까? 모범 사례의 문제입니까?
Dan

14

답은 그 기능을 어떻게 사용할 것인지에 따라 조금씩 다를 수 있습니다. 가장 간단한 대답을 위해 배열 대신 실제로 원하는 것이 벡터라고 결정하십시오. 벡터는 평범한 포인터에 저장할 수있는 지루하고 평범한 값처럼 모든 세상을보기 때문에 좋습니다. 다른 옵션과 그 이후에 원하는 옵션을 살펴 보겠습니다.

std::vector<int> fillarr( std::vector<int> arr ) {
    // do something
    return arr;
}

이것은 당신이 기대하는 것을 정확하게 할 것입니다. 단점은 std::vector모든 것이 깨끗하게 처리되도록하는 것입니다. 단점은 배열이 큰 경우 매우 많은 양의 데이터를 복사한다는 것입니다. 실제로 배열의 모든 요소를 ​​두 번 복사합니다. 먼저 함수가 벡터를 매개 변수로 사용할 수 있도록 벡터를 복사합니다. 그런 다음 다시 복사하여 발신자에게 반환합니다. 벡터 관리를 직접 처리 할 수 ​​있다면 훨씬 쉽게 할 수 있습니다. (발신자가 더 많은 계산을 수행하기 위해 일종의 변수에 저장 해야하는 경우 세 번째로 복사 할 수 있음)

실제로하려고하는 것은 컬렉션을 채우는 것 같습니다. 컬렉션의 새 인스턴스를 반환해야 할 특별한 이유가 없다면 그렇지 않습니다. 우리는 이렇게 할 수 있습니다

void fillarr(std::vector<int> &  arr) {
    // modify arr
    // don't return anything
}

이 방법으로 개인 복사본이 아닌 함수에 전달 된 배열에 대한 참조를 얻을 수 있습니다. 매개 변수를 변경하면 호출자가 볼 수 있습니다. 원하는 경우 참조를 반환 할 수는 있지만 전달 한 것과 다른 것을 얻는다는 것을 의미하기 때문에 실제로는 좋은 생각이 아닙니다.

컬렉션의 새 인스턴스가 실제로 필요하지만 스택에 포함시키지 않으려면 (그리고 모든 복사본에 포함되는) 피하지 않으려면 해당 인스턴스를 처리하는 방법에 대한 일종의 계약을 만들어야합니다. 가장 쉬운 방법은 스마트 포인터를 사용하는 것입니다. 스마트 포인터는 누군가가 붙잡고있는 한 참조 된 인스턴스를 유지합니다. 범위를 벗어나면 깨끗하게 사라집니다. 이렇게 보일 것입니다.

std::auto_ptr<std::vector<int> > fillarr( const std::vector<int> & arr) {
    std::auto_ptr<std::vector<int> > myArr(new std::vector<int>);
    // do stuff with arr and *myArr
    return myArr;
}

대부분의 *myArr경우 일반 바닐라 벡터를 사용하는 것과 동일하게 작동합니다. 이 예는 또한 const키워드 를 추가하여 매개 변수 목록을 수정합니다 . 이제 복사하지 않고 참조를 얻지 만 수정할 수 없으므로 호출자는 함수가 도착하기 전과 동일하다는 것을 알고 있습니다.

이 모든 것이 부풀어 있지만 관용적 인 C ++은 컬렉션 전체에서 거의 작동하지 않습니다. 더 일반적으로 해당 콜렉션에 대해 반복자를 사용합니다. 그게 이런 식으로 보일 것입니다

template <class Iterator>
Iterator fillarr(Iterator arrStart, Iterator arrEnd) {
    Iterator arrIter = arrStart;
    for(;arrIter <= arrEnd; arrIter++)
       ;// do something
    return arrStart;
}

이 스타일을 보는 데 익숙하지 않으면 조금 이상하게 보입니다.

vector<int> arr;
vector<int>::iterator foo = fillarr(arr.begin(), arr.end());

foo는 이제 수정 된 시작을 가리 킵니다 arr.

이것에 대해 정말 좋은 점은 일반 C 배열 및 다른 많은 유형의 컬렉션과 마찬가지로 벡터에서 동일하게 작동한다는 것입니다.

int arr[100];
int *foo = fillarr(arr, arr+100);

이제이 질문의 다른 곳에서 제공되는 평범한 포인터 예제와 끔찍하게 보입니다.


구문이 잘못 &되었습니다. 다음 유형 뒤에 기호가 나타나야합니다.void fillarr(std::vector<int> & arr)
David Rodríguez-dribeas

9

이:

int fillarr(int arr[])

실제로 다음과 동일하게 취급됩니다.

int fillarr(int *arr)

이제 실제로 배열을 반환하려면 해당 줄을 다음으로 변경할 수 있습니다

int * fillarr(int arr[]){
    // do something to arr
    return arr;
}

실제로 배열을 반환하지는 않습니다. 배열 주소의 시작 부분에 대한 포인터를 반환합니다.

그러나 배열을 전달할 때 포인터 만 전달한다는 것을 기억하십시오. 따라서 배열 데이터를 수정하면 실제로 포인터가 가리키는 데이터가 수정됩니다. 따라서 배열을 전달하기 전에 수정 된 결과 외부에 이미 있음을 알고 있어야합니다.

예 :

int fillarr(int arr[]){
   array[0] = 10;
   array[1] = 5;
}

int main(int argc, char* argv[]){
   int arr[] = { 1,2,3,4,5 };

   // arr[0] == 1
   // arr[1] == 2 etc
   int result = fillarr(arr);
   // arr[0] == 10
   // arr[1] == 5    
   return 0;
}

필러 기능에 길이를 넣는 것을 고려해 볼 수 있습니다.

int * fillarr(int arr[], int length)

그렇게하면 길이를 사용하여 배열을 길이에 관계없이 채울 수 있습니다.

실제로 올바르게 사용하십시오. 다음과 같이하십시오 :

int * fillarr(int arr[], int length){
   for (int i = 0; i < length; ++i){
      // arr[i] = ? // do what you want to do here
   }
   return arr;
}

// then where you want to use it.
int arr[5];
int *arr2;

arr2 = fillarr(arr, 5);

// at this point, arr & arr2 are basically the same, just slightly
// different types.  You can cast arr to a (char*) and it'll be the same.

배열을 기본값으로 설정하기 만하면 내장 memset 함수를 사용해보십시오.

다음과 같습니다 : memset ((int *) & arr, 5, sizeof (int));

그래도 주제에 있습니다. 당신은 C ++을 사용한다고 말합니다. STL 벡터 사용을 살펴보십시오. 코드가 더 강력 할 것입니다.

많은 튜토리얼이 있습니다. 다음은 그것들을 사용하는 방법에 대한 아이디어를 제공합니다. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html


std::copy이상 사용하면 memset더 안전하고 쉽습니다. (더 빠르지 않으면 빨리)
GManNickG 08/08/13

5

함수에서 배열을 반환하려면 해당 배열을 구조에 정의하십시오. 이렇게 생겼어요

struct Marks{
   int list[5];
}

이제 타입 구조의 변수를 만들어 봅시다.

typedef struct Marks marks;
marks marks_list;

다음과 같은 방법으로 배열을 함수에 전달하고 값을 할당 할 수 있습니다.

void setMarks(int marks_array[]){
   for(int i=0;i<sizeof(marks_array)/sizeof(int);i++)
       marks_list.list[i]=marks_array[i];
}

배열을 반환 할 수도 있습니다. 배열을 반환하려면 함수의 반환 유형은 구조 유형, 즉 마크 여야합니다. 실제로는 배열을 포함하는 구조를 전달하기 때문입니다. 따라서 최종 코드는 다음과 같습니다.

marks getMarks(){
 return marks_list;
}

5

이것은 상당히 오래된 질문이지만 많은 답변이 있기 때문에 2 센트를 넣을 것입니다. 그러나 가능한 모든 방법을 명확하고 간결한 방식으로 표시하지는 않습니다 (간결한 비트에 대해서는 확실하지 않습니다. TL; DR 😉).

OP가 코드를 더 예쁘게 보이도록 다른 함수로 전달하기 위해 호출자에게 직접 전달하는 수단으로 복사하지 않고 전달 된 배열을 반환하기를 원한다고 가정합니다.

그러나 이와 같은 배열을 사용하려면 포인터로 붕괴하여 컴파일러 가 배열 처럼 취급하도록하십시오 . 이렇게하면 배열에 5 개의 요소가있을 것으로 예상하지만 호출자는 실제로 다른 번호로 전달하는 등의 배열을 전달하면 미묘한 버그가 발생할 수 있습니다.

더 잘 처리 할 수있는 몇 가지 방법이 있습니다. A의 패스 std::vector또는 std::array(하지 않도록 경우 std::array질문을 질문 할 때 2010 년의 주위에 있었다). 그런 다음 객체를 복사 / 이동하지 않고도 객체를 참조로 전달할 수 있습니다.

std::array<int, 5>& fillarr(std::array<int, 5>& arr)
{
    // (before c++11)
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }

    // Note the following are for c++11 and higher.  They will work for all
    // the other examples below except for the stuff after the Edit.

    // (c++11 and up)
    for(auto it = std::begin(arr); it != std::end(arr); ++it)
    { /* do stuff */ }

    // range for loop (c++11 and up)
    for(auto& element : arr)
    { /* do stuff */ }

    return arr;
}

std::vector<int>& fillarr(std::vector<int>& arr)
{
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }
    return arr;
}

그러나 C 배열을 사용한다고 주장하는 경우 배열의 항목 수에 대한 정보를 유지하는 템플릿을 사용하십시오.

template <size_t N>
int(&fillarr(int(&arr)[N]))[N]
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

그러나, 그것은보기 흉한보기에 매우보기 힘들다. 나는 이제 2010 년에 없었던 것을 돕기 위해 무언가를 사용하며, 함수 포인터에도 사용합니다.

template <typename T>
using type_t = T;

template <size_t N>
type_t<int(&)[N]> fillarr(type_t<int(&)[N]> arr)
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

이것은 타입을 예상 한 위치로 이동 시켜서 훨씬 더 읽기 쉽게 만듭니다. 물론 템플릿을 사용하는 것은 5 가지 요소 이외의 다른 것을 사용하지 않을 경우 불필요하므로 하드 코딩 할 수 있습니다.

type_t<int(&)[5]> fillarr(type_t<int(&)[5]> arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

내가 말했듯이, type_t<>이 질문을 할 때 내 트릭은 효과가 없었습니다. 그때 당신이 기대했을 수있는 가장 좋은 것은 구조체에 유형을 사용하는 것이 었습니다.

template<typename T>
struct type
{
  typedef T type;
};

typename type<int(&)[5]>::type fillarr(typename type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

어느 것이 다시보기 흉한 것처럼 보이지만 typename컴파일러에 따라 선택 사항이었을 수도 있지만 적어도 여전히 더 읽기 쉽습니다 .

type<int(&)[5]>::type fillarr(type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

물론 내 도우미를 사용하지 않고 특정 유형을 지정할 수 있습니다.

typedef int(&array5)[5];

array5 fillarr(array5 arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

당시 자유 기능 std::begin()std::end()존재하지 않았다는하지만 쉽게 구현 될 수 있었다. 이것은 배열이 C 배열에서 의미가 있기 때문에 더 안전한 방식으로 배열을 반복 할 수 있었지만 포인터는 아닙니다.

배열에 액세스하는 경우 동일한 매개 변수 유형을 사용하는 다른 함수에 배열을 전달하거나 별칭을 만들 수 있습니다 (이 범위의 원본을 이미 가지고 있으므로 의미가 없습니다). 배열 참조에 액세스하는 것은 원래 배열에 액세스하는 것과 같습니다.

void other_function(type_t<int(&)[5]> x) { /* do something else */ }

void fn()
{
    int array[5];
    other_function(fillarr(array));
}

또는

void fn()
{
    int array[5];
    auto& array2 = fillarr(array); // alias. But why bother.
    int forth_entry = array[4];
    int forth_entry2 = array2[4]; // same value as forth_entry
}

요약하면 배열을 반복하려는 경우 포인터가 배열로 붕괴되지 않도록하는 것이 가장 좋습니다. 컴파일러가 발에 걸리지 않도록 보호하고 코드를 읽기 어렵게 만드는 것은 나쁜 생각입니다. 그렇게 할 이유가없는 한, 가능한 한 오랫동안 타입을 유지함으로써 컴파일러가 당신을 도울 수 있도록 항상 노력하십시오.

편집하다

아, 그리고 완전성을 위해 포인터로 포인터의 성능을 저하시킬 수는 있지만 배열을 보유하는 요소 수와 분리시킵니다. 이것은 C / C ++에서 많이 수행되며 일반적으로 배열의 요소 수를 전달하여 완화됩니다. 그러나 실수를하고 요소 수에 잘못된 값을 전달하면 컴파일러가 도움을 줄 수 없습니다.

// separate size value
int* fillarr(int* arr, size_t size)
{
    for(int* it = arr; it != arr + size; ++it)
    { /* do stuff */ }
    return arr;
}

크기를 전달하는 대신 끝 포인터를 전달하면 배열 끝을 지날 수 있습니다. 이것은 std 알고리즘에 더 가까운 것, 시작 및 끝 포인터를 취하는 것에 유용하지만 반환하는 것은 이제는 기억해야 할 것입니다.

// separate end pointer
int* fillarr(int* arr, int* end)
{
    for(int* it = arr; it != end; ++it)
    { /* do stuff */ }
    return arr;
}

또는이 함수가 5 개의 요소 만 취하고 함수 사용자가 어리석은 짓을하지 않기를 희망 할 수 있습니다.

// I document that this function will ONLY take 5 elements and 
// return the same array of 5 elements.  If you pass in anything
// else, may nazal demons exit thine nose!
int* fillarr(int* arr)
{
    for(int* it = arr; it != arr + 5; ++it)
    { /* do stuff */ }
    return arr;
}

반환 값은 원래 형식을 잃어 포인터로 저하됩니다. 이로 인해, 이제 어레이를 오버런하지 않도록 스스로 할 수 있습니다.

당신은 std::pair<int*, int*>시작과 끝을 위해 그것을 사용할 수있는를 전달할 수 있습니다. 그러나 그 배열은 실제로 배열처럼 보이지 않습니다.

std::pair<int*, int*> fillarr(std::pair<int*, int*> arr)
{
    for(int* it = arr.first; it != arr.second; ++it)
    { /* do stuff */ }
    return arr; // if you change arr, then return the original arr value.
}

void fn()
{
    int array[5];
    auto array2 = fillarr(std::make_pair(&array[0], &array[5]));

    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

또는

void other_function(std::pair<int*, int*> array)
{
    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

void fn()
{
    int array[5];
    other_function(fillarr(std::make_pair(&array[0], &array[5])));
}

재밌지 만, 이것은 std::initializer_list작업 방식 (c ++ 11) 과 매우 유사 하지만이 맥락에서는 작동하지 않습니다.


3

이 작업을 수행하는 가장 간단한 방법은 참조로 반환하는 것입니다. '&'기호를 쓰지 않아도 참조로 자동 반환됩니다.

     void fillarr(int arr[5])
  {
       for(...);

  }

2
int *fillarr(int arr[])

당신은 여전히 ​​같은 결과를 사용할 수 있습니다

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();

나는 'int [] fillarr ...'가 합법적이라고 생각하지 않습니다. 'int * fillarr'은 배열 포인터 동등성으로 인해 사용할 것입니다.
seand

1

위에서 언급했듯이 경로가 정확합니다. 그러나 함수의 로컬 배열 변수를 반환하면 가비지 값을 요소로 반환하는 경우가 있습니다.

배열을 동적으로 생성하고 진행해야한다는 것을 피하기 위해. 이것과 같은 것입니다.

int* func()
{
  int* Arr = new int[100];
  return Arr;
}

int main()
{
  int* ArrResult = func();
  cout << ArrResult[0] << " " << ArrResult[1] << endl;
  return 0;
} 




0
template<typename T, size_t N>
using ARR_REF = T (&)[N];

template <typename T, size_t N>
ARR_REF<T,N> ArraySizeHelper(ARR_REF<T,N> arr);

#define arraysize(arr) sizeof(ArraySizeHelper(arr))


0

출처 : https://www.tutorialspoint.com/cplusplus/cpp_return_arrays_from_functions.htm

C ++에서는 전체 배열을 함수의 인수로 반환 할 수 없습니다. 그러나 인덱스없이 배열 이름을 지정하여 배열에 대한 포인터를 반환 할 수 있습니다.

  1. 함수에서 단일 차원 배열을 반환하려면 다음 예제와 같이 포인터를 반환하는 함수를 선언해야합니다.
int * myFunction()    {
   .
   .
   .
}
  1. C ++은 로컬 변수의 주소를 함수 외부로 반환하는 것을 옹호하지 않으므로 로컬 변수를 정적 변수로 정의해야합니다.

현재 질문에 이러한 규칙을 적용하여 다음과 같이 프로그램을 작성할 수 있습니다.

# include <iostream>

using namespace std;

int * fillarr( );


int main ()
{

   int *p;

   p = fillarr();

   for ( int i = 0; i < 5; i++ )
       cout << "p[" << i << "] : "<< *(p + i) << endl;

    return 0;
}


int * fillarr( )
{
    static int  arr[5];

    for (int i = 0; i < 5; ++i)
        arr[i] = i;

    return arr;
 }

출력은 다음과 같습니다.

p[0]=0
p[1]=1
p[2]=2
p[3]=3
p[4]=4

0

그리고 어떻습니까 :

int (*func())
{
    int *f = new int[10] {1,2,3};

    return f;
}

int fa[10] = { 0 };
auto func2() -> int (*) [10]
{
    return &fa;
}

0

실제로 함수 내에서 배열을 전달하면 원래 배열에 대한 포인터가 함수 매개 변수에 전달되므로 해당 함수 내 배열에 대한 변경 사항은 실제로 원래 배열에서 이루어집니다.

#include <iostream>

using namespace std;

int* func(int ar[])
{
    for(int i=0;i<100;i++) 
        ar[i]=i;
    int *ptr=ar;
    return ptr;
}


int main() {
    int *p;
    int y[100]={0};    
    p=func(y);

    for(int i=0;i<100;i++) 
        cout<<i<<" : "<<y[i]<<'\n';
}

그것을 실행하면 변경 사항을 볼 수 있습니다


1
올바른 영어 단어를 사용하고 (u'll 대신 사용) "buddy"와 같은 빈 문구를 생략하십시오.
hellow

또한 "실제로 참조로 전달됩니다"는 잘못되었습니다. 변수 y자체는 자체의 복사본으로 전달되지만 포인터이기 때문에 배열에서 직접 작동합니다. 답을 수정하십시오.
hellow

stackoverflow.com/questions/5573310/… TL; DR "그러므로 두 형식은 동일합니다."
hellow

그렇습니다. 기술적으로 배열입니다. 맞습니다. 복사되는 것은 배열 자체가 아니라 배열에 대한 포인터입니다.
hellow

0

해결해야 할 이런 종류의 문제에 대한 전체 예는 다음과 같습니다.

#include <bits/stdc++.h>
using namespace std;
int* solve(int brr[],int n)
{
sort(brr,brr+n);
return brr;
}

int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
    cin>>arr[i];
}
int *a=solve(arr,n);
for(int i=0;i<n;i++)
{
    cout<<a[i]<<endl;
}

return 0;
}

-2

다음과 같이 type []을 반환 값으로 정의하십시오.

        private string[] functionReturnValueArray(string one, string two)
    {

        string[] x = {one, two};


        x[0] = "a";
        x[1] = "b";

        return x;
    }

. . . 함수 호출 :

string[] y;
y = functionReturnValueArray(stringOne, stringTwo)

5
이것은 C ++이 아닙니다
Adrian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.