首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++拷贝构造函数、临时函数和拷贝语义

C++拷贝构造函数、临时函数和拷贝语义
EN

Stack Overflow用户
提问于 2010-02-24 10:15:11
回答 3查看 1.5K关注 0票数 17

对于此计划

代码语言:javascript
复制
#include <iostream>
using std::cout;

struct C 
{
    C() { cout << "Default C called!\n"; }
    C(const C &rhs) { cout << "CC called!\n"; }
};

const C f()
{
    cout << "Entered f()!\n";
    return C();
}

int main()
{
    C a = f();
    C b = a;

    return 0;
}

我得到的输出是:

代码语言:javascript
复制
Entered f()!
Default C called!
CC called!

因为f()是按值返回的,所以它应该返回一个临时的。由于T a = x;T a(x);,它不会调用复制构造函数来构造a,并将临时传入的参数作为其参数吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-24 10:19:58

由于f()是按值返回的,因此它应该返回一个临时的。由于T a = x;T a(x);,它不会调用复制构造函数来构造a,并将临时传入的参数作为其参数吗?

查找返回值优化。默认情况下,此选项处于启用状态。如果你是在Windows上使用MSVC 2005+,你可以使用/Od来关闭这个功能并获得想要的结果(或者在GCC上使用-fno-elide-constructors )。此外,有关MSVC的信息,请参阅this文章。

12.8复制类对象

15当满足某些条件时,允许实现忽略类对象的复制构造,即使对象的复制构造函数和/或析构函数有副作用。在这种情况下,实现将被省略的复制操作的源和目标简单地视为引用同一对象的两种不同方式,并且该对象的破坏发生在两个对象在没有优化的情况下将被销毁的较晚时间。115在以下情况下允许这种复制操作的省略(可以组合以消除多个副本):

-在具有类返回类型的函数中的返回语句中,当表达式是具有与函数返回类型相同的cv-类型的非易失性自动对象的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制操作。在抛出表达式中,当操作数是非易失性自动对象的名称时,可以通过将自动对象直接构造到异常对象中来省略从操作数到异常对象(15.1)的复制操作

-当未绑定到引用(12.2)的临时类对象将被复制到具有相同的cv未限定类型的类对象时,可以通过将临时对象直接构造到被省略的副本的目标中来省略复制操作

-当异常处理程序的异常声明(第15条)声明了与异常对象(15.1)相同类型的对象(cv限定除外)时,如果程序的含义除了执行异常声明声明的对象的构造函数和析构函数的执行之外保持不变,则可以通过将异常声明视为异常对象的别名来省略复制操作。

注意:重点是我的

票数 14
EN

Stack Overflow用户

发布于 2010-02-24 10:18:54

这是编译器支持的返回值优化(RVO)特性的一个示例。

当您按值返回时,复制构造函数可能不会被调用。

使用GCC上的-fno-elide-constructors选项关闭该功能。

票数 4
EN

Stack Overflow用户

发布于 2010-02-24 10:24:59

我相信它叫.

我假设当f()返回C对象时,该对象被分配在调用方法的堆栈空间中,因此初始化C a不需要复制。这是您的default C called

代码语言:javascript
复制
C b = a

这会导致一个复制构造函数,从而导致您的CC called

顺便说一句,wiki上的示例看起来与您的代码非常相似。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2323225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档