C++ 特征复制构造函数与运算符=性能

C++ 特征复制构造函数与运算符=性能,c++,eigen,C++,Eigen,在我的工作中,我使用Eigen数学库。我遇到了一种行为,在我自己的类的初始值设定项列表中使用特征矩阵副本构造函数要比在构造函数体中使用操作符=慢得多 在这些示例中,“矩阵”是静态大小的密集矩阵 class Slow { public: Slow(const Matrix &m) : my_matrix{m} {} private: Matrix my_matrix; } class Fast { public:

在我的工作中,我使用Eigen数学库。我遇到了一种行为,在我自己的类的初始值设定项列表中使用特征矩阵副本构造函数要比在构造函数体中使用
操作符=
慢得多

在这些示例中,“矩阵”是静态大小的密集矩阵

class Slow {
    public:
        Slow(const Matrix &m) : my_matrix{m} {}
    private:
        Matrix my_matrix;
}

class Fast {
    public:
        Fast(const Matrix &m) : my_matrix{} {
            my_matrix = m;
        }
    private:
        Matrix my_matrix;
}
我的程序经常调用类的复制构造函数,上面两个选项之间的性能差异非常明显。我验证了生成的程序集实际上是不同的

我知道copy构造函数和operator=是不一样的,但是我很难通过Eigen源代码找出其中一个比另一个快的原因。任何一个拥有一些Eigen专业知识的人都能权衡一下引擎盖下发生了什么,导致operator=速度更快?同样欢迎您提供建议阅读的见解和/或链接。

在“快速”版本中,通过内联、显式循环展开和显式矢量化,由Eigen手动处理副本。在“慢”的情况下,复制向量可以归结为:

template<typename T,int Size>
struct storage {
  T data[Size];
  storage(storage &other)
    : data(other.data)
  {}
};
模板
结构存储{
T数据[大小];
存储(存储和其他)
:数据(其他.数据)
{}
};

我们假设编译器对其进行了适当的优化。不幸的是,如果
Size
有点太大,那么clang和gcc都将此副本作为对
memcpy
的调用来实现,从而丢失编译时
Size
信息。另一方面,让编译器处理此副本可以实现更高级别的优化,例如在某些情况下临时删除。

您意识到,当您使用
操作符=
时,仍然调用默认构造函数,对吗?您正在将复制构造函数与默认构造函数进行比较,后面紧跟着
运算符=
。是的,这是正确的。