Я хочу выделить массив в своем коде, и его размер должен быть определен во время выполнения.
Я пробовал так:
#include <iostream>
#include <array>
int main(){
int M=4,N=3,P=5;
M=N+P;
std::array<std::array<double,M>,N> arr;
}
Но MSVC сказал мне:
a variable with non-static storage duration cannot be used as a non-type argument
Я не нахожу ответа на этот вопрос в stackoverflow. (Существующий вопрос, похоже, не решает мою проблему...)
Как динамически выделить 2D std::array в С++?
Я знаю, что мог бы использовать std::vector
, чтобы решить эту проблему. Но размер векторной памяти должен быть организован мной, и это будет использоваться много раз в моем проекте. И я хочу использовать код типа C++, а не тип C... Может быть, есть способ превратить 2D-массив типа C в std::array
, но я не могу найти его в Google...
Вот и задаюсь этим вопросом...
Я имею в виду, что M и N должны быть получены динамически (не изменены, но я могу знать это только во время выполнения...), например:
#include <iostream>
int main(){
int a=3;
int b=4;
int rowCount=a+b;
int colCout=b-a;
int** a = new int*[rowCount];
for(int i = 0; i < rowCount; ++i)
{
a[i] = new int[colCount];
}
}
Я знаю, где моя ошибка. У меня возник логичный вопрос... Если я не использую push_back, вектор работает хорошо. Если я его использую, массив тоже не работает.
Я думаю, что емкость вектора больше, чем его размер, я хочу этого избежать. Но другой вопрос: Как ограничить емкость std::vector количеством элементов показывает, что я должен использовать свой распределитель или std::vector::shrink_to_fit()
, чтобы избежать его... (В С++ 17 нет гарантии, если вы используете reserve(n)
)
Если вы хотите использовать код типа C++ вместо кода C для обработки контейнеров, размер которых неизвестен до времени выполнения, вы хотите использовать std::vector. Я не понимаю вопроса.
std::vector
— правильное решение. "Но объем векторной памяти нужно организовать самому" Я не понимаю, что вы хотите сказать.
Возможно, вам нужно показать, почему вы считаете, что std::vector не подойдет для вашей проблемы. Я думаю, что это немного проблема XY.
@drescherjm Поскольку размер векторной памяти больше, чем у того же массива, если я не контролирую сам, я думаю, что должен получить его в конструкторе ...
Возможно, вы хотите выделить одномерный вектор и использовать матричный класс
@LearningLin, в этом нет смысла. std::vector
даст вам именно ту память, которая вам нужна.
@drescherjm Я получу vector.capacity() в конструкторе "fine_vector"
@LearningLin что? Это бессмысленно.
@MarcusMüller Думаю, ты прав. Я имею в виду, что если я не использую push_back, размер памяти должен быть таким, каким я хочу. Спасибо.
есть конструктор std::vector
, с помощью которого вы можете указать точный размер, см. (3) в списке в cppreference - (отредактируйте также упоминается в ответе Маркуса Мюллера, который я только что видел)
@drescherjm Да, это проблема XY.
Динамически выделяемый контейнер массива в C++ — это std::vector
. std::array
предназначен специально для массивов фиксированная длина во время компиляции.
https://cppreference.com твой друг!
But the vector memory size needs to be organized by myself
Не совсем уверен, что вы имеете в виду, но вы указываете размер своего std::vector
с помощью конструктора.
std::vector<std::vector<int>> arr(N);
Если вам нужен какой-то специальный распределитель (не только new
/malloc
), вы также можете указать собственный распределитель.
Вся ваша программа, которую вы предлагаете, не является хорошим C++. Решение C++ будет выглядеть так:
#include <vector>
int main() {
int a = 3;
int b = 4;
unsigned int rowCount = a + b;
unsigned int colCount = b - a;
std::vector<std::vector<int>> matrix(rowCount);
for (auto& row : matrix) {
row.resize(colCount);
}
}
Хорошо, я понял. Думаю, мне следует определить для него новый тип.
@LearningLin Я не думаю, что в этом был смысл
...Что? Каков ваш вывод из этого?
@LearningLin нет, дело было вовсе не в этом. Вам не нужен новый тип. Существующий std::vector<std::vector<int>>
просто работает.
@MarcusMüller Думаю, ты прав. Я имею в виду, что если я не использую push_back, размер памяти должен быть таким, каким я хочу. Спасибо
Верен ли мой ответ? Я имею в виду, что емкость вектора может быть больше вектора. И я хочу этого избежать. В С++ 17 другой вопрос показывает, что нет метода, если я не использую свой распределитель. Он выходит в С++ 20?
Я не понимаю, о чем ты меня здесь спрашиваешь. Но если что-то существовало в C++17, оно будет существовать и в C++20. Кроме того, вы, кажется, думаете, что избыточное выделение ресурсов — это действительно плохо, но это не так. Если страницы памяти, выделенные для вектора, не затрагиваются, они не используют физическую память. Таким образом, максимум, что вы тратите впустую, может быть чуть меньше 4 КБ в ОЗУ. Которые вы бы тоже потратили впустую с new
или malloc
, вы просто не замечаете.
std::array
, как и настоящий массив в C++, требует постоянного размера. Это то, что дает ему какое-либо преимущество перед std::vector
.
Для технического объяснения того, как реализуется это требование, помните, что параметры шаблона должны быть константами времени компиляции (поскольку это изменяет способ генерации кода, опять же во время компиляции).
В любом случае, вы хотите использовать std::vector
здесь. Если вы знаете нужный размер, укажите его в качестве параметра конструктора.
Хорошо, я понял. Думаю, мне следует определить для него новый тип.
@LearningLin совсем не то, что сказал Блинди. Вы, должно быть, неправильно поняли!
@MarcusMüller Я знаю, где я неправильно понял, спасибо.
Вам нужен std::vector. std::array имеет фиксированный размер во время компиляции.