У меня есть следующий код ниже,
std::complex<double>** x;
x = calloc(10,sizeof(complex <double> *));
Этот код не удалось скомпилировать со следующим сообщением об ошибке.
error: invalid conversion from 'void*' to 'std::complex<double>*' [-fpermissive]
Как я могу успешно скомпилировать? Почему этот код не компилируется?
В C ++ void *
не приводится автоматически к другим указателям (в отличие от C). Так что если вы используете malloc
и семью в C ++, вам нужно привести результат самостоятельно.
Тем не менее, вы должны отметить, что malloc
не понимает конструкторы C ++. Поэтому, если вы хотите выделить объект C ++ (например, не структуру C или, точнее, POD), вам следует использовать new
(а также delete
/delete[]
соответственно) который правильно заботится о конструкторах и деструкторах.
Кроме того, вы можете использовать одну из многих структур, предоставляемых стандартной библиотекой, например: std::vector
,
Вы пытаетесь написать C ++, как если бы это был C, который допускает опасные неявные преобразования, подобные этой.
Чтобы выделить динамический массив размером 10, используйте
std::vector<std::complex<double>> numbers(10);
и, если вы действительно хотите указатель на первый элемент
x = numbers.data();
Этот код из вопроса,…
x = calloc(10,sizeof(complex <double> *));
это плохо по двум причинам:
в отличие от C, C ++ не имеет неявного преобразования от void*
, а также
создание зубчатого массива с помощью C ++ new
достаточно плохо, делать это с помощью функций выделения уровня С — это вообще мерзость (кроме случаев, когда это требуется для какой-то функции, которую нужно вызвать).
Первый пункт — почему он не компилируется в C ++.
Чисто технический исправить это использовать приведение, а затем предпочтительно C ++ с именем приведение, такое как static_cast
или же reinterpret_cast
, Оба отлично работают на практике для преобразования из void*
, Однако на мой взгляд reinterpret_cast
выражает концептуальную операцию более правильно, поэтому я бы выбрал это — если Я решил сыграть.
Немного лучшим решением является использование C ++ new
вместо С calloc
, С new
Вы должны добавить пустые скобки в конце, чтобы получить гарантированную нулевую инициализацию calloc
, Но главная проблема по-прежнему заключается в том, что каждый низкий уровень и трудно (много работы), чтобы получить право.
Гораздо лучшим общим решением является использование класса контейнера C ++.
Стандартная библиотека предлагает std::vector
, с помощью которого зубчатый массив может быть построен следующим образом:
typedef complex<double> Complex;
typedef vector<Complex> ComplexVec;
typedef vector<ComplexVec> ComplexVec2D;
ComplexVec2D x( 10 );
Тогда каждый ComplexVec
можно просто изменить размер, так как std::vector
динамически изменяемый массив
Если вы действительно хотите матрица, то есть массив массивов равной длины, тогда вместо зубчатого массива рассмотрим класс C ++, который просто обеспечивает двумерную индексацию в одном векторе.
В стиле C ++ 03 это может выглядеть следующим образом (без кода манжеты):
typedef complex<double> Complex;
class ComplexMatric
{
private:
vector<Complex> items_;
int width_;
public:
Complex& operator()( int x, int y )
{ return items_[y*width_ + x]; }
Complex const& operator()( int x, int y ) const
{ return items_[y*width_ + x]; }
ComplexMatrix( int w, int h )
: items_( w*h )
, width_( w )
{}
};
И вы бы использовали это так:
ComplexMatrix x( 10, some_height );
Это включает в себя правильное распределение и освобождение, и даже поддержку копирования по назначению.
Отказ от ответственности: код не тронут руками компилятора.
Вместо того, чтобы использовать calloc
попробуйте использовать new[]
оператор вместо. Это способ C ++ для динамического создания массива.
x = new complex<double>[10];
new[]
возвращает указатель на любой тип, следующий за оператором, в данном случае это указатель с типом complex<double>
который указывает на массив complex<double>
с 10 элементами внутри.
Знайте, однако, вы должны использовать delete[]
оператор для освобождения памяти (не free()
). Иначе никто не знает, что произойдет :-).
delete[] x;
Предполагая ваш x
имеет тип std::complex<double>*
, вы получаете эту ошибку, потому что calloc
возвращает void
указатель. Без -fpermissive
неявные приведения не допускаются. Итак, вам придется бросить между void*
а также std::complex<double>*
, Тем не менее, в C ++ рекомендуется использовать new
вместо malloc
или же calloc
и лично я бы порекомендовал вам использовать std::vector
,