копирование статического массива в динамический массив

#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));
 

Это обеспечит правильную очистку памяти кучи даже в случае исключения и использует механизм отладки реализации, чтобы защитить вас от таких событий, как переполнение буфера.