【问题标题】:Return two dimensional vector efficiently高效返回二维向量
【发布时间】:2014-01-22 09:32:33
【问题描述】:

我有一个问题,如何从函数中有效地返回一个大的二维向量。 我的任务是读取一个大文件并返回一个矩阵数据。

设计一:

 std::vector<std::vector<double> > loadMatrix(const char* fileName){
      //read file
      return matrix;
 }

这个效率不高。

设计二:

 std::vector<std::vector<double> >& loadMatrix(const char* fileName){
      //read file
      return matrix;
 }
 //get some errors

我只是想知道有没有办法解决这个问题。

【问题讨论】:

  • 为什么说效率不高?您是否对优化进行了分析?
  • 首先,不要返回对本地对象的引用(不是低效,是UB)。其次,如果您的编译器支持 C++11,则按值返回。否则考虑使用交换技巧。无论哪种方式,配置文件配置文件(优化之前和优化之后)。
  • 对于 C++11,第一个很可能会移动而不是复制。对于第二个变体,存在未定义行为的风险(如果您返回对局部变量的引用)。
  • 还有第三种选择:将“矩阵”作为非常量引用参数传递给函数,并返回布尔成功/失败指示符。
  • @JoachimPileborg 我怀疑它会被移动。该副本很可能会被完全删除,因此无需移动任何内容。

标签: c++ matrix


【解决方案1】:

如果向量是在函数中创建的,那么您的第一个实际上是未定义的行为。如果向量是在函数内部创建的,您可以像这样简单地返回它:

std::vector<std::vector<double> > loadMatrix(const char* fileName){
    std::vector<std::vector<double> > matrix;
    //read file
    return matrix;
}

感谢RVO(返回值优化),matrix 对象将被移动(或副本将被省略)。

【讨论】:

    【解决方案2】:

    交换技巧涉及交换值而不是赋值,当您可以负担进行破坏性复制时:

    原代码:

    std::vector<std::vector<double> > loadMatrix(const char* fileName){
        //read file
        return matrix; // Uses RVO
    }
    
    // create copy of temporary object returned by loadMatrix
    std::vector<std::vector<double> > result = loadMatrix("matrixfile");
    

    交换技巧:

    std::vector<std::vector<double> > result;
    
    result.swap(loadMatrix("matrixfile"));
    

    交换技巧将指针与临时指针交换。这将导致loadMatrix 返回的临时对象销毁一个空对象(在result 中默认构造的对象)并且result 接收该值而无需任何深度复制或重新分配。

    交换技巧是在 C++11 移动语义之前按值返回的快速解决方案。

    【讨论】:

      【解决方案3】:

      顺便说一句,如果您的编译器不支持移动语义,您也可以在此函数中初始化矩阵:

      bool loadMatrix(const char* fileName, std::vector<std::vector<double> > & matrix)
      {
          // shows if something went wrong
          bool returnFlag = true;
      
          // read file and init matrix 
          return returnFlag;
      }
      
      // create matrix
      std::vector<std::vector<double> > matrix;
      if (true == loadMatrix("matrixfile", matrix))
      {
          // do something
      }
      

      在这种情况下,不会执行矩阵复制。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 2017-05-05
        • 2021-08-16
        • 1970-01-01
        相关资源
        最近更新 更多