【问题标题】:How to initialize a matrix in a function and return it efficiently in C++?如何在函数中初始化矩阵并在 C++ 中有效地返回它?
【发布时间】:2019-03-27 23:09:24
【问题描述】:

我的任务是在函数中生成一个由零组成的方阵并返回它。有很多方法可以做到这一点,但我决定不使用按值返回矩阵以提高效率。我采用了像in this answer 这样的指针方法,但由于它需要手动清理内存(而且据我所知最好使用智能指针),我决定将它变成std::unique_ptr,但我无法获得它工作。这是我的代码:

#include <iostream>
#include <memory>

std::unique_ptr<std::unique_ptr<int>[] > GenerateMatrix(const int &n) {
    std::unique_ptr<std::unique_ptr<int>[] > matrix(new std::unique_ptr<int>[n]);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i].get()[j] = 0;
        }
    }

    return matrix;
}

int main() {
    int n = 4;
    auto matrix = GenerateMatrix(n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            std::cout<<matrix[j].get()[i]<<" ";
        }
        std::cout<<std::endl;
    }

    return 0;
}

我在这里做错了什么?这种方法是否正确?

【问题讨论】:

  • std::unique_ptr&lt;std::unique_ptr&lt;int&gt;[]&gt; 不是二维矩阵。你想要std::unique_ptr&lt;std::unique_ptr&lt;int[]&gt;[]&gt;
  • std::vector&lt;std::vector&lt;int&gt;&gt; 可能包含在课堂上。 (如果已包装,则将向量展平并手动进行索引计算以实现缓存友好)
  • 在这种情况下使用std::unique_ptr 并没有好处。
  • “有很多方法可以做到这一点,但我决定不使用按值返回矩阵以提高效率。”这个假设是错误的——请理解返回值优化保证复制省略士气:过早优化是万恶之源
  • 复制省略和移动语义都可以更好地在此处使用普通的std::vector 并按值返回。

标签: c++


【解决方案1】:

为什么不让你的生活更轻松

vector<vector<int>> generate (int m, int n)
{
    return vector<vector<int>>(m ,vector<int>(n));
}

int main()
{
    int m = 3, n = 4;
    auto matrix = generate(m, n);  // a 3-by-4 matrix of zeros
    return 0;
}

【讨论】:

  • 此解决方案的性能问题是它不会将数据连续存储在内存中。
【解决方案2】:

仅仅依靠保证复制省略返回值优化

std::vector<int> GenerateMatrix(const int &n) {
    return std::vector<int>(n*n, 0);//, 0 can be omitted (as elements will then be zero-initialized)
}

【讨论】:

  • 看来你对std::vector&lt;int&gt;(0, n*n)的参数顺序有误。
  • @Bob__ 我已添加您的评论...作为评论:)
【解决方案3】:

您可以在编译时创建和初始化矩阵。例如:

template<int RowCount, int ColumnCount, int DefaultValue = 0>
struct Matrix
{
  static_assert(RowCount >= 0 && ColumnCount >=0,
                "The number of rows and columns should be positive");
  struct Row
  {
    int column[ColumnCount] = { DefaultValue };
  };
  Row row[RowCount];
};

并像这样使用它:

Matrix<2, 2, 33> matrix;
auto val = matrix.row[0].column[0]; // val == 33
matrix.row[0].column[0] = 55;
val = matrix.row[0].column[0]; // val == 55

当按行和列引用其元素时,请注意矩阵维度。

【讨论】:

  • 或者只是std::array&lt;std::array&lt;T, N&gt;, N&gt;
  • 请注意,您的默认值仅适用于matrix[x][0],matrix[x][1] 将是0
【解决方案4】:

您没有为矩阵分配足够的内存。更改此行:

std::unique_ptr&lt;std::unique_ptr&lt;int&gt;[] &gt; matrix(new std::unique_ptr&lt;int&gt;[n*n]);

另外,我只会使用 i*n + j 进行访问,因为您实际上是在处理一维数组:

#include <iostream>
#include <memory>

std::unique_ptr<std::unique_ptr<int>[] > GenerateMatrix(const int &n) {
  std::unique_ptr<std::unique_ptr<int>[] > matrix(new std::unique_ptr<int>[n*n]);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      matrix.get()[i*n+j] = 0;
    }
  }

  return matrix;
}

int main() {
  int n = 4;
  auto matrix = GenerateMatrix(n);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      std::cout<<matrix.get()[i*n+j]<<" ";
    }
    std::cout<<std::endl;
  }

  return 0;
}

【讨论】:

    猜你喜欢
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多