高效返回二维向量

Posted

技术标签:

【中文标题】高效返回二维向量【英文标题】: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 我怀疑它会被移动。该副本很可能会被完全删除,因此无需移动任何内容。 【参考方案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

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

【讨论】:

以上是关于高效返回二维向量的主要内容,如果未能解决你的问题,请参考以下文章

字符串的内存高效向量

3个向量的高效排序算法

使用角度向量的高效 3D 旋转

MATLAB 中复杂向量的高效分类

基于向量加权平均值的高效优化算法(Matlab代码实现)

使用 AVX2 高效计算 std::complex<float> 向量的绝对值