std :: array vs массив C-Style для непрерывной памяти

Последовательность псевдослучайных чисел, поступающих от вызова (s) до random_number, зависит от алгоритма, используемого процессором, и значения семени.

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

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

Как указано в другом ответе , внутреннее random_seed можно использовать для установки значение семени и перезапустить псевдослучайный генератор. Опять же, это зависит от процессора, что происходит, когда вызов call random_seed() (то есть без аргумента put=). Некоторые процессоры будут перезапускать генератор с повторяемой последовательностью, а некоторые - нет. gfortran (опять же, перед версией 7) находится в первой категории.

Для процессоров, где call random_seed() приводит к повторяемой последовательности, для генерации отдельных последовательностей потребуется явное переменное семя во время выполнения. Пример для более старых версий gfortran можно найти в документации .

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

В заключительной заметке в проекте стандарта Fortran 2018 есть предложение по внутреннему random_init. Это обрабатывает оба случая выбора повторяемости между вызовами и различиями над изображениями (coarray).

0
задан Oneiros 13 July 2018 в 13:09
поделиться

4 ответа

Для справки, метод, к которому вы обращаетесь, называется flexible array member, и, к сожалению, он не поддерживается в C ++ как функция ядра или стандартная библиотечная функция. Я нахожу это неутешительным.

std::array - это одетый массив C-стиля (с некоторыми членами, которые позволяют использовать его в качестве контейнера STL, например, итерации, калибровки, интроспекции типа и т. Д.).

Единственный способ узнать функциональность, которая была бы похожа на гибкий элемент массива, заключалась бы в создании std::vector<char> с размером, заданным в заголовке sizeof(header) + <extra bytes for payload>, а не placement new в vector.data() ]. Вы можете обернуть все это в класс-помощник, чтобы сохранить некоторую типизацию для нескольких сценариев.

1
ответ дан SergeyA 17 August 2018 в 12:51
поделиться

A std::array не содержит указателя на данные где-то еще, а std::array непосредственно хранит данные внутри, там нет ничего динамичного.

Он был разработан для обеспечения семантики, аналогичной к стандартным массивам, но с некоторыми характеристиками стандартных контейнеров STL.

Это совокупный класс, который в основном реализуется как

namespace std
{
  template<typename T, size_t S>
  class array
  {
    T __elems_[S];
  }
}

У вас есть array.data(), который уже возвращает массив C поэтому я не получаю ваше требование.

2
ответ дан Jack 17 August 2018 в 12:51
поделиться

Я могу предложить стирание типа как общее решение вашей проблемы. В современном C ++ существует тенденция избегать прямого манипулирования необработанными указателями, если это не неизбежно:

struct common_part{
    //declare common data and ctor
protected:
    virtual elem* end(){return begin()+size();};
    virtual elem *begin()=0 ;
    virtual ~common_part()=default;
    virtual std::size_t size()=0;
};

template<std::size_t N>
struct instance_type:
    common_part{
protected:
    void elem* begin() override{return arr;};
    void elem* end() override{return arr+N;};
    void std::size_t size() override{return N;};
private:
    elem arr[N];
};

std::unique_ptr<common_part> ptr {new instance_type<N>{}};
0
ответ дан Red.Wave 17 August 2018 в 12:51
поделиться
  • 1
    почему вы хотите virtual членов, когда вам не нужен полиморфизм? шаблонов более чем достаточно для этой цели. – Jack 13 July 2018 в 17:30
  • 2
    для стирания типа. в противном случае пара {begin, end} должна быть объявлена ​​как общий элемент данных и обработана специально. полиморфизм времени выполнения является более гибким, надежным, но компактным и экономичным подходом. В случае раздувания кода элемент данных для {begin, end} выглядит лучше, но в конце dtor должен быть виртуальным, так что правильный dtor выбирается указателем после удаления. – Red.Wave 13 July 2018 в 18:45

Итак, мой вопрос: начинается ли std :: array с указателем или его можно использовать так же, как родной массив C-стиля?

Из документация

Этот контейнер является агрегированным типом с той же семантикой, что и структура, содержащая массив C-style T [N] в качестве единственного нестатического элемента данных.

Таким образом, там нет другого элемента данных, а именно массив T[N], который вы хотели.

Вы можете тривиально подтвердить это для себя, используя sizeof или взглянув на код.

. В стороне, имена, начинающиеся с _[A-Z], зарезервированы для реализации, поэтому вы, вероятно, не должны называть параметры вашего шаблона _T и _N.

3
ответ дан Useless 17 August 2018 в 12:51
поделиться