Определение и инициализация списка отдельно в C ++ - PullRequest
2 голосов
/ 08 января 2020

Я пишу плагин для программного обеспечения CFD OpenFOAM на C ++. Мой код будет считывать информацию из каждой ячейки в модели (> 100 тыс. Ячеек) для каждого временного шага анализа. У меня есть список списков парных чисел с именем C, который инициализируется нулями на первом временном шаге и изменяется на следующих временных шагах, однако размер остается прежним.

Моя проблема заключается в том, что инициализация списка на первом этапе занимает слишком много времени. В следующие временные шаги я могу легко l oop по всем элементам в списке, выполнить некоторые вычисления для этих значений и сохранить их снова. Однако на первом шаге времени у меня есть пустой список размером 0, что означает, что у меня слишком много добавлений нулей для его инициализации. Я знаю окончательный размер списка, чтобы я мог легко написать

Foam::List<Foam::List<double>> C (size,0.0);

на первом шаге, и моя проблема была бы решена (это спецификация OpenFOAM c список класса https://www.openfoam.com/documentation/guides/latest/api/classFoam_1_1List.html)

Однако, если я хочу определить свой список списков один раз, а затем использовать его на протяжении всех временных шагов, мне нужно определить его в заголовочном файле. В заголовочном файле я не знаю размера, а это значит, что я определяю его как

Foam::List<Foam::List<double>> C;

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

Если бы это было C#, я мог бы разбейте его на две строки как

List<List<double>> C;
C = new List<List<double>>(size);

и запишите первую строку в файл заголовка и вторую строку в файл C (насколько я понимаю). Как я могу сделать что-то подобное в C ++?

Очень благодарен за помощь в этом.

Спасибо, Дэвид

Ответы [ 3 ]

2 голосов
/ 08 января 2020

Предполагая, что Foam::List<Foam::List<double>> C; определено в вашем .h -файле, а size - это массив из двух элементов, содержащий два размера вашего списка, вы должны иметь возможность:

C=Foam::List<Foam::list<double>>(size[0],Foam::List<double>(size[1],0));

Еще одна вещь, которую, я думаю, вы должны знать, это то, что ключевое слово new не должно использоваться в c ++ для подобных вещей. Ключевое слово new выделяет память в куче, а не в стеке. Каждый раз, когда вы используете new, вы также должны будете использовать delete позже, чтобы избежать утечек памяти. Обычно это делается с помощью new в классах CTOR и delete в классах DTOR. Как правильно указывает @MaxLanghof в современном C ++, вы всегда должны отдавать предпочтение использованию интеллектуальных указателей, таких как std::shared_pointer, std::unique_pointer и std::weak_pointer, а не new и delete

.
1 голос
/ 08 января 2020

Поскольку переменная, которую вы хотите инициализировать, является членом класса, обычным способом ее инициализации является использование списка инициализатора члена конструктора:

Заголовочный файл:

class MyPlugIn
{
public:
  MyPlugIn(int listSize); // constructor
protected:
  Foam::List<Foam::List<double>> C;
};

Исходный файл:

MyPlugIn(int listSize) : C(listSize)
{
}

Это, конечно, требует, чтобы необходимый размер был известен во время создания MyPlugIn. Если это не так, использование оператора назначения копирования / перемещения, как показано в ответе Макса, также является решением.

0 голосов
/ 11 января 2020

Если это простой список, вы можете использовать любой из них, в зависимости от того, требуется ли вам изменение размеров или если он уже имеет правильный размер:

mylist.resize(size, Zero);
mylist = Zero;

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

for (auto &lst : mylistlist)
{
    lst = Zero;
}

Я бы использовал константу Zero вместо 0.0 или что-то еще - это ясно дает смысл и применимо к вектор / тензор и другие величины векторного пространства, если вам это нужно в будущем.

...