优化构造函数调用的数量

Mat*_*rom 13 c++ constructor g++

在工作中,我们有一个带有昂贵构造函数的类,所以我们希望尽可能少地调用它.我们仔细研究了它的用法并尝试使代码更加友好,所以说.

但是我们在g ++编译器中发现了一个奇怪的地方,我们不明白发生了什么.

请考虑operator +的两个实现

const Imaginary Imaginary::operator+(const Imaginary& rhs) const
{
    Imaginary tmp(*this);
    tmp.append(rhs);
    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

const Imaginary Imaginary::operator+(const Imaginary& rhs) const
{
    return Imaginary(*this).append(rhs);
}
Run Code Online (Sandbox Code Playgroud)

我已将打印输出放在各种构造函数中,并使用以下小程序

int main(int argc, char* argv[])
{
    Imaginary x(1, 1);
    Imaginary y(2, 1);

    Imaginary c = x + y;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我通过operator +的第一个实现得到了这个打印

int/int ctor
int/int ctor
Copy ctor
Run Code Online (Sandbox Code Playgroud)

当使用operator +的第二个变体时,我得到以下内容

int/int ctor
int/int ctor
Copy ctor
Copy ctor
Run Code Online (Sandbox Code Playgroud)

在这里我们看到g ++能够在一种情况下优化掉一次对复制构造函数的调用,而不是后一种情况.令我惊讶的是,它设法用更笨拙的实现来实现它,我把它保存到临时.

现在我可以更多地理解它,如果它是另一种方式,但显然它不是,现在我希望也许你可以在这个问题上启发我.

我应该补充一点,当我们添加--no-elide-constructors作为g ++的标志时,我得到以下打印输出

int/int ctor
int/int ctor
Copy ctor
Copy ctor
Copy ctor
Run Code Online (Sandbox Code Playgroud)

问候,马蒂亚斯

Ben*_*igt 5

如果编译器无法内联append,则无法确定返回值是否为目标对象.然后它不知道临时被返回,并且不能在适当的位置构建它.

你会有同样的行为:

Imaginary tmp(*this);
return tmp.append(rhs);
Run Code Online (Sandbox Code Playgroud)

如果返回值对append编译器不透明(在另一个编译单元中定义),则会阻止优化.