C++;操作员';通过模板进行优化 这样,我有一个C++矩阵类,并且有一些重载运算符(像+,*,%,-ATC…),它们看起来像: Matrix operator*(const Matrix& b) const; res = a * n + b * t - k;

C++;操作员';通过模板进行优化 这样,我有一个C++矩阵类,并且有一些重载运算符(像+,*,%,-ATC…),它们看起来像: Matrix operator*(const Matrix& b) const; res = a * n + b * t - k;,c++,templates,optimization,operator-overloading,C++,Templates,Optimization,Operator Overloading,他们返回类型为Matrix的TMP对象,然后复制它,这会降低性能 如果我做了类似的事情 Matrix some = a*b + c*d - (i+j)*m*b; //[1] 调用了6个副本构造函数 因此,我看到ppl正在进行一些模板元编程,以将[1]扩展为: Matrix some = ((a*b)+=(c*d))-=(((i+j)*=m)*=b); //[2] [2]处的代码将调用大约3个复制构造函数。(*=,+=将结果写入左操作数并返回其链接) 你们能给我解释一下,我是如何通过模板做到这

他们返回类型为Matrix的TMP对象,然后复制它,这会降低性能

如果我做了类似的事情

Matrix some = a*b + c*d - (i+j)*m*b; //[1]
调用了6个副本构造函数

因此,我看到ppl正在进行一些模板元编程,以将[1]扩展为:

Matrix some = ((a*b)+=(c*d))-=(((i+j)*=m)*=b); //[2]
[2]处的代码将调用大约3个复制构造函数。(*=,+=将结果写入左操作数并返回其链接)


你们能给我解释一下,我是如何通过模板做到这一点的,或者我应该读些什么来理解如何做到这一点。

所以,正如我在评论中看到的,编译器可以自己优化它,但是,也有一些时刻存在,可以优化

让我们开始吧

  • 首先,通常我们通过operator=保存重载运算符的结果,如果我们在其中添加两个字段{bool tmp,bool copied},我们可以跳过内存处理,它应该是这样的
  • 我们还需要改变一个解构函数

    ~SomeClass()
    {
        if( !(tmp && copied) )//If its not a tmp and not copied then freeing
        {
            ...freeing a memory...
        }//otherwise just skeep
    }
    
  • 在运算符中,我们通常为结果对象调用构造函数,但是,如果其中一个对象是tmp,如果可能的话,为什么不在其中保存数据呢
  • 所以。。。通过这些操作,我们减少了被调用操作的数量,我们保存了一个否则将被分配的内存,我们也没有从操作符结果中复制内存

    现在,代码如下:

    Matrix operator*(const Matrix& b) const;
    
    res = a * n + b * t - k;
    

    将只为“a*n”和“b*t”分配内存,然后所有内容都将存储在这些运算符结果的tmp对象中。最后,我们不是将内存(值)从tmp对象转移到“res”,我们只是简单地将指针分配到一个“tmp”内存(不会被释放)。

    他们要搜索的关键字是“表达式模板”

    不过,很多事情都可以通过使用右值引用来实现


    顺便说一句,如果你真的很认真,你会想要比你的例子所暗示的更多的重写;e、 g.乘法和加法步骤通常希望组合成一个操作,而不是两个单独的操作。

    “……然后它被复制,这会降低性能。”读取NRVO/RVO。大多数现代编译器现在都实现了这一点。除了编译器返回值优化和复制省略外,您还可以实现移动运算符和返回对象的
    std::move
    。“大约6”度量优化后的构建实际调用了多少复制构造函数。复制省略:调用的复制构造函数不是6,而是零。将一些输出放入复制构造函数中,使用
    /O2
    或调用编译器的任何标志进行编译,然后亲自查看。