Тело инициализации массива как параметр функции (C-массив), возможно ли это? - PullRequest
20 голосов
/ 05 октября 2011

Я ищу помощь в следующей ситуации:
У меня есть некоторый класс и какой-то метод, синтаксис такой:

class SomeClass {  
    public:  
            void doSomething(int *a);  
};

Итак, я хочу назвать этот метод как

SomeClass::doSomething({ 0, 1, 2, 3, 4 });

Возможно ли это на любом языке? Любая реализация (C ++, C, obj-c, obj-c ++) приветствуется! Я знаю, что этот блок инициализации является телом массива, как

int *a = { 0, 1, 2, 3, 4 };
SomeClass::doSomething(a);

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

Ответы [ 3 ]

23 голосов
/ 05 октября 2011

В C99 это работает:

functionThatTakesIntPtrOrArray( (int []){ 1, 2, 3, 4 } );

.. и подобные вещи можно сделать с помощью структур.

8 голосов
/ 05 октября 2011

Это о C ++ 11 списках инициализаторов (раздел 18.9 ).

void foo (std :: initializer_list <int> inputs) {
    for (auto i : inputs) {
        // ...
    }
}

foo ({10, 20, 30});

Только компилятор может создать список инициализатора, но вы можете обращаться с ним как со стандартным контейнером в стиле STL с begin(), end(), size() и итераторами с произвольным доступом.

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

std :: vector <std :: string> foo {"a", "b"};

эквивалентно

std :: vector <std :: string> foo;
foo .push_back ("a");
foo .push_back ("b");

за исключением того, что он может выполнять меньше распределений. Обратите внимание, что const char* были автоматически превращены в std::string.

2 голосов
/ 25 сентября 2015

Если initializer_list недоступен, а массивы в основном маленькие, есть еще один вариант, перегрузка оператора << для std :: vector, например:

template <typename T>
inline std::vector<T> operator <<( const std::vector<T>& vec, const T& val ) {
    std::vector<T> result(vec);
    result.push_back(val);
    return result;
}

С этим вы можетесделайте это:

void foo (const std::vector<int>& inputs) {
    // ...
}

foo ( std::vector<int>() << 10 << 20 << 30 );

За удобство инициализации в одну строку нужно заплатить цену, при этом нет необходимости указывать размер вектора.Копия предыдущего вектора создается для каждого добавляемого элемента, что делает время выполнения по меньшей мере квадратичным по размеру вектора - поэтому это лучше всего подходит для коротких векторов и случаев, когда производительность не имеет значения.Существует лучшее решение для C ++ 11, как указано в ответе spraff.

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