2010-11-23 3 views
1

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

Я сделал достаточно исследований в этом, чтобы знать, что у вас нет массива или ссылок (хотя я еще не понял, почему), и мне было интересно, может ли кто-нибудь помочь мне разобраться, как это сделать ? Различные методы, которые я пробовал, привели к 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; 
    } 
} 

ответ

5

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

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

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


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

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

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

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

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


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

+0

код в вопросе пытается передать массив * в * функция, а не получить один , – 2010-11-23 23:13:34

+0

@ Энди: он используется как параметр out; функция возвращает результаты через массив, который OP пытается передать по ссылке. Гораздо чище использовать возвращаемые значения вместо параметров. – 2010-11-23 23:14:44

1

эта линия не делает то, что вы ожидаете:

initialise_existing_devices(no_of_existing_devices, existing_devices[100]) 

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

Я бы предположил, что вы используете std::vector<std::string>, а не массив, и передаете это по ссылке.

EDIT: хорошо, учитывая обновление:

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

struct string_array 
{ 
    string data[100]; 
}; 

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

0

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

0

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

initialise_existing_devices(no_of_existing_devices, existing_devices); 

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

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

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

0

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

0

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

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) 
{ 
} 
Смежные вопросы