我有下面的代码,
std::complex<double>** x;
x = calloc(10,sizeof(complex <double> *));
此代码编译失败,并显示以下错误消息。
error: invalid conversion from 'void*' to 'std::complex<double>*' [-fpermissive]
如何成功编译?为什么这个代码编译失败?
您正试图将C++当作C编写,这允许像这样危险的隐式转换。
要分配大小为10的动态数组,请使用
std::vector<std::complex<double>> numbers(10);
如果你真的想要一个指向第一个元素的指针
x = numbers.data();
在C++中,void *
不会自动转换为其他指针(与C不同)。因此,如果在C++中使用malloc
和族,则需要自己投射结果。
但是,您应该注意到malloc
不理解C++的构造函数。因此,如果你想分配一个C++对象(例如不是C结构,或者更准确地说是POD),你应该使用new
(以及相应的delete
/delete[]
),它可以正确地处理构造函数和析构函数。
或者,您可以使用标准库提供的众多结构中的一种,例如std::vector
。
问题
这个代码来自问题,…
x = calloc(10,sizeof(complex <double> *));
不合格有两个原因:
与C不同,C++没有从
void*
和的隐式转换用C++
new
创建一个锯齿状数组已经够糟糕的了,用C级分配函数来创建锯齿状数组通常是令人讨厌的(除非某个函数需要调用)。
第一个要点是它在C++中编译失败的原因。
该怎么办
纯技术修复是使用强制转换,然后最好使用C++命名的强制转换,如static_cast
或reinterpret_cast
。两者在void*
的转换实践中都很好。然而,在我看来reinterpret_cast
更正确地表达了概念操作,因此我认为;d选择–如果我选择选角。
一个稍微好一点的解决方案是使用C++new
而不是Ccalloc
。对于new
,您必须在末尾添加一个空括号,以获得calloc
的保证零初始化。但主要的问题仍然是,每一个低水平的工作都很难(大量的工作)做好。
一个更好的通用解决方案是使用C++容器类。
标准库提供std::vector
,使用它可以像这样构建锯齿状阵列:
typedef complex<double> Complex;
typedef vector<Complex> ComplexVec;
typedef vector<ComplexVec> ComplexVec2D;
ComplexVec2D x( 10 );
然后,由于std::vector
是一个动态大小的数组,因此每个ComplexVec
都可以被调整大小。
如果你真的想要一个矩阵,该怎么办
如果你真的想要一个矩阵,即一个相等长度的数组数组,那么考虑一个C++类,它只提供对单个向量的2D索引,而不是锯齿状数组。
在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>
的指针,指向内部有10个元素的complex<double>
数组。
不过,请注意,您必须使用delete[]
运算符来解除分配内存(而不是free()
)。否则没人知道会发生什么:-)。
delete[] x;
假设x
的类型为std::complex<double>*
,则会出现此错误,因为calloc
返回一个void
指针。如果没有-fpermissive
,则不允许隐式强制转换。因此,您必须在void*
和std::complex<double>*
之间进行转换。然而,在C++中,建议使用new
而不是malloc
或calloc
,我个人建议您使用std::vector
。