【问题标题】:Matrix class in c++?C ++中的矩阵类?
【发布时间】:2012-04-23 15:08:43
【问题描述】:

我一直在尝试编写一个 Matrix 类,我正在使用一个 main 方法来测试它。它不工作......根本。

我不明白为什么 size(allRowValues 的大小除以 double 的大小)为零!

我一直在写一些调试打印,但它没有帮助......我真的非常非常喜欢 C++,所以任何帮助/建议都将不胜感激。

 1 #include "matrix.h"
 2 #include <iostream>
 3 #include <sstream>
 4 
 5 Matrix::Matrix(){
 6 };
 7 
 8 Matrix::Matrix(int rows, int columns, double allRowValues [] ){
 9     this->rows = rows;
10     this->columns = columns;
11     this->matrixValues = new double[rows*columns];
13     std::cout <<"ALL ROW VALUES" <<std::endl;
14     std::cout<<"*****" <<std::endl;
15     std::cout << sizeof (allRowValues) << std::endl;
16     std::cout<<"*****" <<std::endl;
17     std::cout << sizeof(allRowValues[0]) << std::endl;
18     std::cout<<"*****" <<std::endl;
19     int size = sizeof(allRowValues)/sizeof(double);
20     int numberOfValues = rows * columns;
21     int currentIndex = 0;
22     for (int i = 0; i < numberOfValues; i++){
23             std::cout<< "MATRIX CONSTRUCTOR\n";
24             std::cout<<allRowValues <<std::endl;
25             std::cout<<"-----"<<std::endl;
26             std::cout<<index << std::endl;
27             std::cout<<"-----"<<std::endl;
28             std::cout<<size << std::endl;
29             std::cout<<"-----"<<std::endl;
30             if ((allRowValues) && (currentIndex < size)){
31                 std::cout << "ARV " <<std::endl;
32                 std::cout << allRowValues[currentIndex] << std::endl;
33                 this->matrixValues[i]= allRowValues[currentIndex];
34                 std::cout << "MAT " << allRowValues[currentIndex++] << std::endl;
35             }else{
36                 std::cout << "Else\n";
37             }
38         }
39         int index=0;
40         for (int j = 0; j < rows; j++){
41             for (int i = 0; i < columns; i++){
42                 std::cout << this->matrixValues[index++];
43             }
44             std::cout<<std::endl;
45         }
46     };
47 
48     Matrix::Matrix(double* rowValues){
49         int sizeRows = sizeof(rowValues)/sizeof(double);
50         //TODO: throw error for all rows must be the same length
51         this->rows = sizeRows;
52         int sizeColumns = sizeof(rowValues[0])/sizeof(double);
53         this->columns = sizeColumns;
54         this->matrixValues = rowValues;
55     };
56 
57     double Matrix::width(){
58         std::cout << "Width\n";
59         return this->columns;
60     };
61 
62     double Matrix::height(){
63         std::cout << "Height\n";
64         return this->rows;
65     };
66 
67     std::string Matrix::toString(){
68         int numberOfValues = 0;
69         std::cout<<matrixValues[numberOfValues];
70         std::string build_output;
71         std::cout<<matrixValues;
72         for (int i = 0; i < rows; i++){
73             build_output = "[";
74             std::cout << "\n";
75             for (int j = 0; j < columns; j++){
76                 std::cout << "VALUE: " <<matrixValues[numberOfValues];
77                 build_output = matrixValues[numberOfValues];
78                 numberOfValues++;
79             }
80             build_output = " ]";
81         }
82         return build_output;
83     }
84 
85     int main (){
86         double values[6] = {1, 2, 3, 4, 5, 6};
87         std::cout <<"Values: \n";
88         Matrix a = Matrix(2, 3, values);
89         std::cout << a.width() << std::endl;
90         std::cout << a.height() << std::endl;
91         std::cout << a.toString();
92         return 1;
93 }

【问题讨论】:

  • 这是作业吗?如果没有,有很多非常好的为 C++ 编写的矩阵库,这将比自己编写要快得多,而且错误更少。
  • 即使您决定自己执行此操作,也不要强迫用户以交互方式输入数据。让他们把数据放在一个文件中,然后给你一个文件名。这将简化您的代码并大大减少用户出错的可能性。
  • sizeof 是一个糟糕的设计。如果您的编译器选择在 32 位机器上制作 int 8 字节,在 64 位机器上制作 16 字节怎么办?不要依赖sizeof
  • @CppLearner 那会是什么问题呢? sizeof 比幻数可靠得多。

标签: c++ matrix


【解决方案1】:

double allRowValues[] 声明一个指针,而不是一个数组。表达式sizeof(allRowValues)/sizeof(double) 然后计算指针大小与double 大小之间的比率。如果双打更大,结果显然为零。

由于某种原因,同样的错误也发生在另一个构造函数中(sizeof(rowValues)/sizeof(double)),但这次参数显然是一个指针。然后是sizeof(rowValues[0])/sizeof(double),它是双精度数组(即双精度)的一个元素的大小与双精度的大小(显然是一)之间的比率。

似乎有人相信sizeof 运算符可以神奇地知道给定指向其第一个元素的指针的数组的大小。它不能。或者数组和指针之间可能存在混淆。他们是not the same

大多数时候,数组(即T[N] 类型的对象,如double[100])只是衰减为指向其第一个元素的指针(即T*,如double*),在此过程中丢失了大小信息。这就是为什么如果你打算“传递一个数组”,你永远不能只传递一个指针。您需要以某种方式传递尺寸信息。

您可以将大小作为额外参数显式传递,或者传递另一个标记缓冲区结束的指针(迭代器样式)。您还可以传递对数组的引用(防止衰减为指针,从而保留大小信息)并使用模板获取大小信息。

template <std::size_t N, std::size_t M>
void pass_a_2d_array_by_reference(double(&the_array)[N][M]) { // N and M are the sizes
    // do stuff
}

既然您了解了这些问题,那么如果您使用现成的解决方案,您就根本无法拥有它们:

  • std::vector&lt;std::vector&lt;double&gt;&gt;:如果您不需要连续存储,这是一个非常好的解决方案。如果您想要锯齿状阵列,这也是您的最佳选择。
  • boost::multiarray&lt;double, 2&gt;:另一个非常好的解决方案,它同样适用于更多维度的数组;
  • 还有许多其他现有解决方案,可满足各种需求。看看周围吧。

【讨论】:

  • 我还写了一个简单的二维矩阵类模板,您可以查看并从中获取想法,以防这只是一个学习练习:ideone.com/gytw7
  • 可能值得提供一个模板构造函数:template &lt;size_t N, size_t M&gt; Matrix::Matrix( double (&amp;init)[N][M] ),以允许从 C 样式矩阵(通常是 conststatic)进行初始化。
  • 是的!我在您写评论时添加了这一点:)
  • 关于std::vector&lt;std::vector&lt;double&gt; &gt;,它的一个缺点是它允许使用锯齿状数组(你不希望在矩阵中出现这种情况)。当然,如果全部封装在一个类中,确保它们不会出现锯齿状,那也没问题(虽然我还是更喜欢std::vector&lt;double&gt; 并进行手动索引计算)。
【解决方案2】:

如果您坚持使用 c 样式数组(我不推荐),您也可以使用模板化解决方案:

template<int size>
Matrix::Matrix(int rows, int columns, double (&allRowValues) [size] ){
...
}

总的来说,我推荐一个现成的、宽松的开源矩阵库,例如eigen

【讨论】:

    【解决方案3】:

    您应该使用 std::vector&lt;double&gt;&amp;(或 std::array)而不是 c 样式数组 double allRowValues[]。因此,您可以使用allRowValues.size() 轻松获取其大小。

    c++ faq-lite:Why should I use container classes rather than simple arrays?

    参考:
    http://en.cppreference.com/w/cpp/container/vector
    http://en.cppreference.com/w/cpp/container/array

    【讨论】:

    • should 改成 could 我会收回我的-1
    • 我主张应该,尽管可能作为一个额外的构造函数。支持从 C 样式矩阵进行初始化有一个很好的论据,尽管在这种情况下,他应该使用模板构造函数从 C 样式矩阵中获取大小,而不是采用 double*
    • @Shahbaz 我不明白。 c-array 与 c++ 向量相比有什么优势?然后关于 c 样式矩阵,如果矩阵维度是模板参数,我也会看到一个加号。在这种情况下,现在有 std::array&lt;std::array&lt;double,m&gt;,n&gt;
    • @ugo 如果您只需要一个简单的数组,为什么要使用向量?这个答案可能建议一个向量作为替代,这是可以理解的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 2012-11-20
    • 1970-01-01
    相关资源
    最近更新 更多