2015-11-18 72 views
0

这很可能是我试图做的是糟糕的练习。如果是这样,请告诉我,我可以停止。无论如何,我正在使用动态内存来存储矩阵数据数组,从事一些基本的矩阵数学函数。我想弄清楚如何将传递给构造函数的矢量转换为这个数组,但是我得到了一些奇怪的结果。这是简单的版本。使用矢量构造函数分配动态内存

页眉:

class Matrix { 
public: 
    unsigned int size = 4; 
    float *M; 

    Matrix(std::vector<float> values) : M(&values[0]){} 

    ~Matrix() = default; 
}; 

而且测试文件:

int main(){ 
    Matrix m(std::vector<float>{ 0.0f, 0.0f, 0.0f, 1.0f, 
           1.0f, 2.0f, 3.0f, 4.0f, 
           5.0f, 6.0f, 7.0f, 8.0f, 
           9.0f, 10.0f, 11.0f, 12.0f }); 
    return 0; 
} 

结果是...错了。看起来一切正常(从调试时观察值)直到从构造函数返回。我的猜测是Visual Studio的调试器对我说谎,但它早于此发生。

因此,除了尺寸没有改变的事实之外,发生了什么?有一个更好的方法吗?另外,是否有可能接受std :: initializer_list并将该数据提供给动态指针?

回答

2

你传入的矢量是一个临时对象。一旦构造函数完成,临时向量将不再存在,因此您存储的地址(&values[0])将因此指向垃圾。你的代码实际上可能工作,但实际上它也可能会让你的电脑崩溃,或者让你喝咖啡,或者做其他未定义的事情。

如果你想保持相同的接口(即传入一个向量),你需要复制数据。像这样的东西会帮助您了解

Matrix(std::vector<float> values) : M(new float[values.size()]) 
{ 
    std::copy(values.begin(), values.end(), M); 
} 

但现在你必须释放M在你的析构函数,并实施适当的拷贝构造函数和赋值运算符。另外,不要忘记你的移动构造函数和赋值操作符;)查看std::unique_ptrstd::shared_ptr(当然还有std::vector),以获得更好的内存管理方式。

+0

我会补充说,一旦你修改参数来引用,你将会把你的指针var M指向向量的内部存储器。那里的任何改变都会搞砸向量。此外,请注意,该矢量可能携带额外的内存(它分配的内存超过动态增长所需的内存)。 –

+0

所有的真实。尽管我不想让OP有太多的细节超载。问题的实质是他/她持有暂时的指示。 – bstamour

+0

谢谢你,超级快!不幸的是,我试图做你已经建议和标准:复制有一些安全问题。没有足够的确定它的用法来确定什么是错的。 但是,我一定会研究这些指针(heh)。你会说在数组上使用向量会带来很多矩阵的显着性能下降吗? –

0

使用您当前的代码,您正在存储一个悬挂指针。在调用构造函数Matrix后,向量及其数据将被破坏。

您可以使用以下某个选项解决问题。

选项1

不要使用原始指针。改为使用std::vector<float>。通过

std::vector<float> M; 

然后更换

float *M; 

,您可以更新的构造是:

Matrix(std::vector<float> values) : M(values){} 

选项2

分配内存为M,然后复制数据来自构造函数中的输入参数。

Matrix(std::vector<float> values) : M(new float[values.size()]) 
{ 
    std::copy(values.begin(), values.end(), M); 
} 

如果使用此选项,则需要实现适当的复制构造函数,复制赋值运算符和析构函数。请记住在The Rule of Three上阅读。

+0

选项1当然是我想过的。尽管我希望能够使用最轻量级的数据结构,但我不确定性能差异是否显着。 –

+0

@AlexCoats,如果使用'std :: vector'对性能有任何明显的负面影响,我会非常惊讶。 –

相关问题