按值返回内联函数

Mar*_*ark 7 c++ memory optimization inline

我正在实现一些数学类型,我想优化运算符以最小化创建,销毁和复制的内存量.为了演示我将向您展示我的Quaternion实现的一部分.

class Quaternion
{
public:
    double w,x,y,z;

    ...

    Quaternion  operator+(const Quaternion &other) const;
}
Run Code Online (Sandbox Code Playgroud)

我想知道以下两个实现如何不同.我有一个+ =实现,可以在没有创建内存的情况下就地操作,但是一些使用四元数的高级操作对于使用+而不是+ =很有用.

__forceinline Quaternion Quaternion::operator+( const Quaternion &other ) const
{
    return Quaternion(w+other.w,x+other.x,y+other.y,z+other.z);
}
Run Code Online (Sandbox Code Playgroud)

__forceinline Quaternion Quaternion::operator+( const Quaternion &other ) const
{
    Quaternion q(w+other.w,x+other.x,y+other.y,z+other.z);
    return q;
}
Run Code Online (Sandbox Code Playgroud)

我的c ++完全是自学成才的,所以当谈到一些优化时,我不确定该怎么做,因为我不确切知道编译器如何处理这些事情.这些机制如何转换为非内联实现.

欢迎对我的代码提出任何其他批评.

Mic*_*urr 10

您的第一个示例允许编译器可能使用称为"返回值优化"(RVO)的某些操作.

第二个示例允许编译器潜在地使用称为"命名返回值优化"(NRVO)的东西.这两个优化显然密切相关.

可以在此处找到Microsoft实施NRVO的一些细节:

请注意,该文章表明NRVO支持始于VS 2005(MSVC 8.0).它没有具体说明是否同样适用于RVO,但我相信MSVC在8.0版之前使用了RVO优化.

这篇关于Move Constructors的文章由Andrei Alexandrescu提供了有关RVO如何工作的好信息(以及编译器何时以及为何不使用它).

包括这个位:

听到每个编译器(通常是每个编译器版本)都有自己的检测和应用RVO的规则,你会感到很失望.有些人只将RVO应用于返回未命名临时值的函数(最简单的RVO形式).当函数返回的命名结果(所谓的命名RVO或NRVO)时,更复杂的也应用RVO.

从本质上讲,在编写代码时,您可以依赖于您可以根据您编写代码的方式(在"精确"的非常流畅的定义下),月亮的相位以及鞋子的大小,将RVO可移植地应用于您的代码.

这篇文章写于2003年,编译器现在应该有很大的改进; 希望月亮的阶段对于编译器可能使用RVO/NRVO时可能不那么重要(也许它可以用到星期几).如上所述,似乎MS直到2005年才开始实施NRVO.也许是因为有人在微软的编译器上工作时得到了一双比以前更大尺寸的新鞋.

您的示例很简单,我希望两者都能生成具有更新编译器版本的等效代码.

  • 对于当前的编译器,两个片段具有大致相同的优化机会.如今,当代码具有多个返回语句(即使用不同的对象)时应用RVO时编译器真的很难,因为在这种情况下,编译器很难确定应该构造哪些不同的实例返回内存空间. (2认同)

Lor*_*nVS 6

在您提供的两个实现之间,确实没有区别.任何进行任何优化的编译器都会优化您的局部变量.

至于+ =运算符,可能需要一个关于你是否希望你的Quaternions是不可变对象的更多参与讨论...我总是会把这样的对象创建为不可变对象.(但话又说回来,我更像是一个管理编码器)