2013-05-12 80 views
6

我有以下两个功能:为什么我的复制构造函数只在这种情况下调用两次?

Class foo(Class arg) 
{ 
    return arg; 
} 

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

现在,当我只调用foo(ARG),拷贝构造函数当然是所谓的两倍。当我仅仅打电话给酒吧(& arg)时,它只会被调用一次。因此,我期望

foo(bar(&arg)); 

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

在此先感谢!

回答

6

编译器是否认识到另一个副本不需要?

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

每一段的C++ 11标准的12.8/31:

当满足特定条件时,一种实现被允许省略类 对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象 的析构函数具有副作用。在这种情况下,实现将被忽略的复制/移动操作的源和目标视为简单地引用同一对象的两种不同方式,并且销毁该对象 发生在两个对象没有优化就被摧毁了。 复制/移动操作的这个省音,称为复制省略,允许在下列情况下(这 可以合并,以消除多个副本):

- 在return声明函数与类返回类型,当表达式是具有相同cv不合格 类型作为函数返回类型的非易失性自动对象(不包括函数或catch-clause参数)的名称时,复制/移动操作可以通过构造 自动对象直接进入函数的返回值

- [...]

- 当未绑定到引用(12.2)的临时类对象将被复制/移动到具有相同cv不合格类型的类对象时,复制/移动操作可以通过 直接构建临时对象到省略拷贝的目标可以省略/移动

- [...]

随着GCC,你可以尝试使用-fno-elide-constructor编译标志抑制这种优化并查看编译器在没有发生副本删除时的行为。

+0

非常感谢!帮助了我很多! – Veluria 2013-05-12 12:04:10

+0

@Pete:很高兴:) – 2013-05-12 12:04:49

相关问题