为什么在这种情况下我的复制构造函数只被调用两次?

Why is my copy constructor only called twice in this scenario?

本文关键字:两次 调用 这种情况下 我的 复制 构造函数 为什么      更新时间:2023-10-16

我有以下两个函数:

Class foo(Class arg)
{
    return arg;
}
Class bar(Class *arg)
{
    return *arg;
}

现在,当我单独调用foo(arg)时,复制构造函数当然会被调用两次。当我单独调用bar(&arg)时,它只被调用一次。因此,我期望

foo(bar(&arg));

复制构造函数在这里被调用了三次。然而,它仍然只被调用两次。为什么呢?编译器是否认识到不需要另一个副本?

提前感谢!

编译器是否识别出不需要另一个副本?

确实如此。编译器正在执行复制/移动省略。这是所谓的"as-if"规则的唯一例外,它允许编译器(在某些情况下,如您的示例中的情况)忽略对类的复制或移动构造函数的调用,即使这些调用有副作用。

c++ 11标准第12.8/31段:

当满足某些条件时,允许实现省略类的复制/移动构造object, ,即使为复制/移动操作选择了构造函数和/或对象的析构函数有副作用。在这种情况下,实现处理省略的复制/移动的源和目标操作就是引用同一对象的两种不同方式,以及该对象的销毁发生在时间的后期,如果没有优化,两个对象就会被破坏。这种对复制/移动操作的省略,称为copy省略,在以下情况下是允许的可以组合以消除多个副本):

—在具有类返回类型的函数的return语句中,当表达式是a的名称时具有相同cv-不合格的非易失性自动对象(函数或catch子句参数除外)类型作为函数返回类型,则可以通过构造来省略复制/移动操作自动对象直接转化为函数的返回值

— [...]

-没有绑定到引用(12.2)的临时类对象将被复制/移动对于具有相同cv- undefined类型的类对象,可以通过将临时对象直接构造为省略的copy/move

的目标

— [...]

对于GCC,您可以尝试使用-fno-elide-constructor编译标志来抑制此优化,并查看当没有复制省略发生时编译器的行为。