std :: array переменной длины, например

Поскольку мои обычно используемые компиляторы C ++ допускают массивы переменной длины (например, массивы в зависимости от размера времени выполнения), мне интересно, есть ли что-то вроде std::array с переменным размером? Конечно, std::vector имеет переменный размер, но он размещается в куче и перераспределяется при необходимости.

Мне нравится иметь массив, выделенный стеком, размер которого определяется во время выполнения. Есть ли какой-нибудь std-шаблон, в котором это может быть? Может быть, использовать std::vector с фиксированным максимальным размером?


person dronus    schedule 31.12.2013    source источник
comment
При использовании std::array размер массива является параметром шаблона, поэтому он не может быть переменной времени выполнения. Думаю, std::vector - ваш лучший выбор.   -  person Daniel Kamil Kozar    schedule 31.12.2013
comment
Вам нужно изменить размер массива после его создания? Или это просто фиксированный размер во время выполнения?   -  person Joseph Mansfield    schedule 31.12.2013
comment
Кроме того, C ++ 14 будет иметь массивы размера Runtime с автоматической продолжительностью хранения.   -  person Daniel Kamil Kozar    schedule 31.12.2013
comment
Поскольку в языковом стандарте нет стека, этот вопрос трудно сформулировать точным или осмысленным.   -  person Kerrek SB    schedule 31.12.2013
comment
@DanielKamilKozar: Нет, больше нет.   -  person Kerrek SB    schedule 31.12.2013
comment
@KerrekSB: Это отстой.   -  person Daniel Kamil Kozar    schedule 31.12.2013
comment
возможный дубликат Есть ли альтернатива std :: dynarray, доступная в настоящее время?   -  person Benjamin Bannier    schedule 31.12.2013
comment
@DanielKamilKozar: Мех. Было бы довольно странно использовать систему типов, чтобы сделать такое понятие точным. Вы можете сами увидеть эти усилия в истории изменений на Github. Пока что идея заключается в том, что опыта в этом отношении недостаточно, поэтому это откладывается.   -  person Kerrek SB    schedule 31.12.2013
comment
Обычный ответ на это - использовать std::vector с настраиваемым распределителем. Поскольку вы ожидаете, что данные будут расположены в стеке, по-видимому, они всегда будут освобождаться в обратном порядке, в котором они размещены. С учетом этого ограничения, должно быть довольно легко написать чрезвычайно быстрый локальный распределитель потока. Обратной стороной является то, что вы сделаете отдельное выделение заранее для хранения данных, но это не так уж сильно отличается от того, что ОС делает для стека вашего потока - в современной ОС ваш блок является виртуальным только до тех пор, пока он не используется, как и стек. Но это не выиграет от горячего стека в кеше.   -  person Steve Jessop    schedule 31.12.2013
comment
Поскольку мои обычно используемые компиляторы C ++ допускают использование массивов переменной длины, использование этого расширения делает ваш код непереносимым и нестандартным.   -  person Walter    schedule 31.12.2013
comment
@Walter: точно, это, несомненно, мотивация для того, чтобы задать вопрос.   -  person Steve Jessop    schedule 31.12.2013
comment
Нет, но _alloca - ваш друг. Не могу поверить, что никто нигде об этом не упоминал.   -  person user2345215    schedule 31.12.2013
comment
@ user2345215: Вероятно, потому что alloca не слишком хорошо работает с объектами с отслеживанием состояния, и это помечено C ++.   -  person Benjamin Bannier    schedule 31.12.2013
comment
@KerrekSB: Что значит стека нет? Автоматическое хранилище ведет себя так же, как стек, и в спецификации языка он иногда упоминается как стек (например, разворачивание стека при возникновении исключения), так почему бы не назвать его стеком?   -  person Mike Seymour    schedule 31.12.2013
comment
@SteveJessop ¿Значит, мотивация в том, чтобы иметь непереносимый код?   -  person Walter    schedule 31.12.2013
comment
Все мы любим переносимый код. Иногда мне даже больше нравится более быстрый код, если он делает что-то возможным. Однако быстрая и портативная была бы еще лучше.   -  person dronus    schedule 01.01.2014
comment
@Walter: нет. Вопрос заключается в том, есть ли стандартная замена той (нестандартной) функции, о которой спрашивающий знает.   -  person Steve Jessop    schedule 01.01.2014


Ответы (2)


В настоящее время разрабатываются два предложения по переносу в C ++ массивов фиксированного размера во время выполнения, которые могут вас заинтересовать:

Оба они разрабатываются как часть технической спецификации Array Extensions, которая будет выпущена вместе с C ++ 14.

person Joseph Mansfield    schedule 31.12.2013
comment
Так что второй выглядит действительно хорошо. Есть ли реализации на сегодняшний день? - person dronus; 31.12.2013
comment
@JosephMansfield, возможно, это следует объединить в здесь? - person M.M; 04.11.2014

Как сказал Даниэль в комментарии, размер std::array указывается как параметр шаблона, поэтому его нельзя установить во время выполнения.

Однако вы можете построить std::vector, передав минимальную емкость через параметр конструктора:

#include <vector>

int main(int argc, char * argv[])
{
    std::vector<int> a;
    a.reserve(5);
    std::cout << a.capacity() << "\n";
    std::cout << a.size();

    getchar();
}

Но. Содержимое неподвижного вектора будет храниться в куче, а не в стеке. Проблема в том, что компилятор должен знать, сколько места должно быть выделено для функции до ее выполнения, поэтому просто невозможно хранить данные переменной длины в стеке.

person Spook    schedule 31.12.2013
comment
На самом деле вы не устанавливаете минимальную емкость с помощью параметра конструктора. Это устанавливает начальный размер, и, поскольку size<=capacity это работает. Чтобы установить емкость, используйте reserve. - person Benjamin Bannier; 31.12.2013
comment
@BenjaminBannier Вы правы. Фактически цель была бы достигнута, но решение с запасом намного элегантнее. - person Spook; 31.12.2013
comment
Это основано на куче, поэтому я не хочу этого и задал свой вопрос ... Однако, если std::vector может быть реализован для выделения его исходной емкости в стеке и переключения на кучу при первом перераспределении. Это не будет работать с reserve, так как это должно быть выполнено при первом распределении ... но было бы круто. Однако я сомневаюсь, что в обычной реализации это работает. - person dronus; 31.12.2013