Как я могу передать массив по ссылке на функцию в C ++? - PullRequest
1 голос
/ 24 ноября 2010

У меня есть следующая программа, в которой две переменные должны быть переданы по ссылке на функцию, где их значения будут определены на основе внешних факторов, прежде чем они будут возвращены в main(), чтобы они могли использоваться другими функциями. Первая переменная, которую я пытаюсь передать, это int, и это нормально, но другая - это массив строк, что вызывает у меня некоторые проблемы.

Я провел достаточно исследований по этому вопросу, чтобы понять, что у вас не может быть массива или ссылок (хотя мне еще предстоит выяснить, почему), и мне было интересно, сможет ли кто-нибудь помочь мне выяснить, как это сделать? Различные методы, которые я попробовал, привели к segmentation faults.

NB : В приведенном ниже коде массив передается по значению, поскольку я просто не знаю, что для него написать.

Обновление : мне нужно использовать массив для моей курсовой работы. Некоторые другие структуры данных, такие как vector, которые были предложены, были бы хороши, но я должен использовать определенные структуры.

void initialise_existing_devices(int& no_of_existing_devices, string existing_devices[100]);

int main()
{
    int no_of_existing_devices = 0;
    string existing_devices[100];

    initialise_existing_devices(no_of_existing_devices, existing_devices[100]);
}

void initialise_existing_devices(int& no_of_existing_devices, string existing_devices[100])
{
    string line;
    ifstream DeviceList;
    DeviceList.open("devices/device_list");
    while (true)
    {
        getline(DeviceList, line, '\n');
        if (DeviceList.eof())
        {
            break;
        }
        ++ no_of_existing_devices;
    }
    DeviceList.close();

    DeviceList.open("devices/device_list");
    for (int i = 0; i < no_of_existing_devices; i ++)
    {
        getline(DeviceList, line, '\n');
        existing_devices[i] = line;
    }
}

Ответы [ 6 ]

5 голосов
/ 24 ноября 2010

Ссылка на массив выглядит следующим образом:

void f(std::string (&a)[N]) { }

, где a - это имя параметра, а N - количество элементов в массиве.


Однако, обычно в C ++ вы не передаете массив по ссылке (вы можете; это просто не распространено).Другие параметры включают:

  • Передать указатель на начальный элемент массива;в этом случае рассмотрите возможность передачи размера массива в качестве второго аргумента функции.

  • Используйте взамен std::vector<std::string> или std::array<std::string, N> и передайте его по ссылке (вы можететакже найдите psuedo-контейнер array в Boost; кроме этого, подумайте над написанием собственного. Если вы посмотрите на исходный код Boost, он довольно прост и понятен).

  • Передайте пару итераторов (начало и конец) функции и используйте их для управления диапазоном.

Последний вариант - самый идиоматический подход C ++;он также является наиболее общим, потому что вы можете использовать любой тип контейнера, включая массивы, контейнеры стандартной библиотеки или контейнеры, которые вы написали сами.


Поскольку вы на самом деле пытаетесь использовать параметр какпараметр "out", вероятно, лучше просто вернуть std::vector<string> или std::array<string, 100>, содержащие результаты;это намного чище.

1 голос
/ 24 ноября 2010

эта строка не делает то, что вы ожидаете:

initialise_existing_devices(no_of_existing_devices, existing_devices[100])

подсказка: индекс массива, 100 ...

Я бы посоветовал вам использовать std::vector<std::string> вместомассив и передать его по ссылке.

РЕДАКТИРОВАТЬ: хорошо, учитывая обновление:

Можете ли вы использовать struct?Если это так, вы можете обернуть массив в struct:

struct string_array
{
  string data[100];
};

, а затем определить его экземпляр в main и передать его по ссылке?Я уверен, что вы можете заполнить детали ..:)

0 голосов
/ 24 ноября 2010

Вы можете использовать шаблоны, например так:

template <size_t size> 
initialise_existing_devices(int& no_of_existing_devices, string (&existing_devices)[size])
{
}

или вы можете сделать:

typedef string hundred_strings[100];

initialise_existing_devices(int& no_of_existing_devices, hundred_strings &existing_devices)
{
}
0 голосов
/ 24 ноября 2010

Это одна из тех вещей, которые С ++ имеет общее с С. Массивы не передаются по значению. Они понижены до указателей на свои первые элементы. Синтаксис массива в параметрах функции по сути является просто комментарием. Вы можете сказать, выполнив sizeof(existing_devices) внутри вызова функции. Таким образом, ответ на ваш вопрос заключается в том, что вы уже делаете это.

0 голосов
/ 24 ноября 2010

Для фактического аргумента используйте только имя массива, которое представляет адрес массива:

initialise_existing_devices(no_of_existing_devices, existing_devices);

Для параметра используйте это для постоянного указателя на массив:

void initialise_existing_devices(int& no_of_existing_devices, string existing_devices[])

Тем не менее, использование std :: vector в качестве возвращаемого типа или ссылочного параметра позволит избежать необходимости угадывать количество устройств перед вызовом.

0 голосов
/ 24 ноября 2010

Вы должны использовать std::vector<T> для массивов, управляемых кучей, или boost:: / std::array<T, N> для массивов на основе стека.Эти объекты будут иметь свой собственный размер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...