#c #arrays
#c #массивы
Вопрос:
Я определяю динамический массив на c :
double *values;
int size = 5;
values = new (nothrow) double[size];
Я знаю, что это работает, потому что он компилируется, но я вижу некоторые потенциальные проблемы.
Допустим, я хочу присвоить значения этому массиву:
double samples = [1,2,3,4,5,6];
values = samples; //runtime error: free or corruption
Что именно происходит, чтобы сгенерировать эту ошибку?
Комментарии:
1. Может быть, вы имеете в виду
double samples[] = {1,2,3,4,5,6};
2. «Я знаю, что это работает, потому что он компилируется». Интересный подход.
3. Вы не присваиваете значения
values
, вы просто указываете на первый элементsamples
.4.
values = samples;
на самом деле не вызывает никаких ошибок. Это заставляет указательvalues
указывать на этот массив. Однако, если вы попытаетесь позже, будет ошибкаdelete[] values;
, потому что вы попытаетесь удалить что-то, что неnew
было ‘d.
Ответ №1:
Вы должны использовать std::copy
для копирования статического массива в динамический массив, как в примере ниже:
#include <iostream>
#include <algorithm>
int main() {
int *a = new int[5];
int b[] = {1, 2, 3, 4, 5};
std::copy(b, b 5, a);
for(std::size_t i(0); i < 5; i) std::cout << a[i] << " ";
std::cout << std::endl;
return 0;
}
В качестве альтернативы, если вам нужно удобство присваивания вместо поэлементного копирования и при условии, что вы знаете размер массивов во время компиляции и ваш компилятор поддерживает функции C 11, используйте std::array
s, как в примере ниже:
#include <iostream>
#include <array>
int main() {
std::array<int, 5> a;
std::array<int, 5> b {{1, 2, 3, 4, 5}};
a = b;
for(auto i : a) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
Однако рекомендуется предпочесть std::vector
использование необработанных динамических массивов, подобных приведенному ниже примеру:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> a(5);
int b[] = {1, 2, 3, 4, 5};
std::copy(b, b 5, a.begin());
for(auto i : a) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
Комментарии:
1. Вы не должны публиковать какие-либо решения, которые включают new[] .
Ответ №2:
Это не работает, потому что вы присваиваете статический массив указателю.
double *values;
double samples[] = {1,2,3,4,5,6};
Для компилятора это два разных типа данных.
Когда вы говорите:
values = new double[size];
Вы создаете блок кучи (динамической) памяти, а «значения» содержат адрес памяти первого элемента в массиве. Чтобы заполнить значения из вашего статического массива, вам нужно назначить каждый элемент по отдельности следующим образом:
values[0] = samples[0];
values[1] = samples[1];
// or better yet
for (int i = 0; i < size; i )
values[i] = samples[i]
Комментарии:
1. Когда вы говорите
new double[size]
, вы создаете утечки памяти и переполнения буфера.
Ответ №3:
Вы можете использовать a std::vector
, который имеет конструктор итератора, это решит проблему для вас.
std::vector<double> values(std::begin(samples), std::end(samples));
Это обеспечит правильную очистку памяти кучи даже в случае исключения и использует механизм отладки реализации, чтобы защитить вас от таких событий, как переполнение буфера.