массив указателей как параметр функции - PullRequest
3 голосов
/ 12 ноября 2009

У меня есть базовый вопрос о массиве и указателе в C / C ++.

Скажи, что у меня есть:

Foo* fooPtrArray[4];

Как передать fooPtrArray в функцию? Я пробовал:

int getResult(Foo** fooPtrArray){}  //  failed
int getResult(Foo* fooPtrArray[]){} // failed

Как мне работать с массивом указателей?

РЕДАКТИРОВАТЬ: Я когда-то думал, что сообщение об ошибке из-за передачи неправильного массива указателей, но из всех ответов, я понимаю, что это что-то еще ... (назначение указателя)

Error msg:
Description Resource Path Location Type incompatible types in assignment of 
`Foo**' to `Foo*[4]' tryPointers.cpp tryPointers line 21 C/C++ Problem

Я не совсем понимаю, почему там написано: Foo * * Foo * [4]. Если в качестве параметра функции они взаимозаменяются друг с другом, то почему во время присваивания возникает ошибка компиляции?

Я попытался продублировать сообщение об ошибке с минимальным кодом следующим образом:

#include <iostream>

using namespace std;

struct Foo
{
int id;
};

void getResult(Foo** fooPtrArray)
{
cout << "I am in getResult" << endl;
Foo* fooPtrArray1[4];
fooPtrArray1 = fooPtrArray;
}

int main()
{
Foo* fooPtrArray[4];
getResult(fooPtrArray);
}

Ответы [ 5 ]

11 голосов
/ 12 ноября 2009

Оба

int getResult(Foo** fooPtrArray)

и

int getResult(Foo* fooPtrArray[])

а также

int getResult(Foo* fooPtrArray[4])

будет отлично работать (все они эквивалентны).

Из вашего вопроса не ясно, в чем была проблема. Что "не удалось"?

При такой передаче массивов обычно имеет смысл также передавать количество элементов, поскольку прием, позволяющий типу массива переходить в тип указателя, обычно используется специально для разрешения передачи массивов разных размеров

int getResult(Foo* fooPtrArray[], unsigned n);
...
Foo* array3[3];
Foo* array5[5];
getResult(array3, 3);
getResult(array5, 5);

Но если вы всегда будете передавать массивы строго из 4 элементов, лучше использовать указатель с другим типом в качестве параметра

int getResult(Foo* (*fooPtrArray)[4])

В последнем случае вызов функции будет выглядеть следующим образом

Foo* array[4];
getResult(&array);

(обратите внимание на оператор &, примененный к объекту массива).

И, наконец, поскольку этот вопрос помечен как C ++, в последнем случае вместо указателя также может использоваться ссылка

int getResult(Foo* (&fooPtrArray)[4]);
...
Foo* array[4];
getResult(array);
2 голосов
/ 12 ноября 2009

То, что вы объявили со следующей строкой:

Foo* fooPtrArray[4];

- это массив указателей на Foo объектов (другими словами, массив Foo*).

В C / C ++ имя массива определяется как указатель на начало массива. Это связано с тем, что массивы не являются «настоящими» типами в этих языках, а представляют собой просто непрерывную последовательность значений определенного типа в памяти.

Имя fooPtrArray в этом случае будет «указателем на первый указатель» в массиве, который является началом ячейки памяти, где хранится массив указателей.

Так что любой прототип функции, который вы описали выше, должен работать. Однако при передаче массивов в функцию вам всегда нужно будет также указывать размер, чтобы функция знала, сколько там элементов. Поэтому вы должны определить свой метод следующим образом:

int getResult(Foo** fooPtrArray, int arraySize);

Внутри этой функции вы можете получить доступ к отдельным Foo указателям (и впоследствии Foo объектам) в массиве следующим образом:

for (int i=0; i < arraySize; i++)
{
    Foo* fooPtr = fooPtrArray[i];
    if (fooPtr)
    {
        fooPtr->memberFunction();
        fooPtr->memberVariable;
    }
}
0 голосов
/ 12 ноября 2009

Я не понимаю, как это можно скомпилировать без возврата int?!

@ Кинопико, ваш код не компилируется в C ++.

@ Лили, какое сообщение об ошибке вы получаете? в вашем примере getResult должен вернуть int. Это вероятно то, что терпит неудачу.

0 голосов
/ 12 ноября 2009

Верхний компилируется ОК:

http://codepad.org/KOcnpmtv

Второй тоже в порядке:

http://codepad.org/7OSqprYI

0 голосов
/ 12 ноября 2009

Обе эти сигнатуры функций выглядят так, как будто они должны работать. При вызове функции вы должны сделать что-то вроде этого:

int returnValue;
returnValue = getResult(fooPtrArray);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...