Что предпочесть - функцию с переменным количеством аргументов или передачу массива/вектора указателей void*?
Пожалуйста подскажите, что лучше, эллипсис или вектор void указателей? По-идее одно и то же, но может в кого производительность более лучше? Спасибо.
Пример эллипсиса:
#include <iostream>
#include <cstdarg> // требуется для использования эллипсиса
double findAverage(int first, ...)
{
// Обработка первого значения
double sum = first;
// Мы получаем доступ к эллипсису через va_list, поэтому объявляем переменную этого типа
va_list list;
// Инициализируем va_list используя va_start. Первый параметр - это список, который нужно инициализировать.
// Второй параметр - это последний параметр, который не является эллипсисом
va_start(list, first);
int count = 1;
// Бесконечный цикл
while (1)
{
// Используем va_arg для получения параметров из эллипсиса.
// Первый параметр - это va_list, который мы используем.
// Второй параметр - это ожидаемый тип параметров
int arg = va_arg(list, int);
// Если текущий параметр является контрольным значением, то прекращаем выполнение цикла
if (arg == -1)
break;
sum += arg;
count++;
}
// Выполняем очистку va_list, когда уже сделали всё необходимое
va_end(list);
return sum / count;
}
int main()
{
std::cout << findAverage(1, 2, 3, 4, -1) << '\n';
std::cout << findAverage(1, 2, 3, 4, 5, -1) << '\n';
return 0;
}
Ответы (2 шт):
Видимо, имеется в виду Эллипсис (или неопределённое количество параметров в функции, функция с переменным количеством аргументов), который имеет синтаксис
<return_type> function(arg1, ...); //... - и есть эллипсис
Полезная в некоторых случаях вещь, однако имеет синтаксис, который быстро забывается в виду крайне нерегулярного его использования (сугубо на мой дилетантский взгляд, конечно же). Прежде чем использовать эллипсис, следует для начала создать переменную типа va_list, которая и хранит массив аргументов эллипсиса. Затем следует инициализировать эту переменную функцией va_start. Аргументы можно получить функцией va_arg, в котором указывается индекс аргумента и его предполагаемый тип данных. Завершается использование эллипсиса вызовом va_end для очистки массива. Однако же, с вектором мороки будет меньше. Его не требуется инициализировать в самой функции. Да и количество аргументов мы точно знаем, в отличии от эллипсиса, при инициализации которого в функции va_start необходимо указать ПРЕДПОЛАГАЕМОЕ количество аргументов. Но в обоих случаях остаётся минус, связанный с типами данных - мы до конца не знаем какие типы данных имеют аргументы. Поэтому в обоих случаях наверняка необходимо использовать разные методы, например строку-декодер, которая сообщит как трактовать аргументы. Но по производительности эллипсис будет получше, думаю. В любом случае, тема очень интересна и хотелось бы услышать ответы опытных программистов!
Освобождая всех от ответственности за мое мнение (с) Жванецкий, что ли...
Использовать функцию с переменным числом параметров - последнее дело. Потому что нет никакой проверки типов, надо согласовывать, грубо говоря, протокол вызова, чтобы знать, когда закончатся аргументы... Далее, вы по сути не в состоянии динамически изменить количество этих аргументов во время выполнения, после компиляции. Написали руками три аргумента - значит, будет три, и чтоб получить четыре - надо перекомпилировать программу.
Если использовать массив/вектор/еще что-то - это уже куда лучше (по крайней мере, тут вы можете менять динамически размер). Проверка типов... Ну, тут есть варианты. Так, как вы написали - через void* - это, скорее всего, с приведением типов, так что строгой типизации и безопасности типов тут не будет, но это уже хоть что-то.
Так что я при прочих равных за нормальные типы данных, а не три точки вместо них :) При этом я не говорю, что их нельзя использовать ни в коем случае - просто надо всегда сопоставлять преимущества и недостатки для каждого конкретного применения.
По поводу быстродействия - не думаю, что влияние будет заметно, потому что отличие будет... ну, на одно разыменование. Так что исходить нужно из критериев, отличных от преждевременной оптимизации :)