免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2855 | 回复: 4
打印 上一主题 下一主题

[C++] C++疑问?关于copy constructor? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-08-31 05:40 |只看该作者 |倒序浏览
  1. #include <iostream>;
  2. using namespace std;

  3. class X {
  4. public:
  5.   X()         throw();
  6.   X(const X&) throw();
  7. };

  8. X::X()         throw() { cout << "default constructor\n"; }
  9. X::X(const X&) throw() { cout << "copy constructor\n";    }

  10. X userCode(X b) throw()                     
  11. {
  12.   X c = b;                                       
  13.   return c;
  14. }                                                   

  15. int main()
  16. {
  17.   X a;
  18.   cout << "calling userCode()\n";
  19.   X d = userCode(a);
  20.   cout << "back in main()\n";
  21. }

复制代码


以上代码,书上的输出如下:

default constructor
calling userCode()
copy constructor
copy constructor
copy constructor
back in main()


我在windows下用g++,输出如下:

default constructor
calling userCode()
copy constructor
copy constructor
back in main()

少了一次copy  constructor调用。
我发现是这个语句 X d = userCode(a);没有调用copy constructor。



难道是书上错了?Addison.Wesley.Cpp.FAQs.2nd.Edition


谢谢!

论坛徽章:
0
2 [报告]
发表于 2005-08-31 08:38 |只看该作者

C++疑问?关于copy constructor?

如果是看程序,应该是调用3次
main()中1次(不算函数调用)
userCode调用两次。

论坛徽章:
0
3 [报告]
发表于 2005-08-31 10:29 |只看该作者

C++疑问?关于copy constructor?

编译器的优化所致。

如果没有任何优化,拷贝构造函数应该被调用 4 次:
  • 函数实参 a 和虚参 b 结合时
  • 函数内 c 创建并用 b 来初始化时
  • 函数返回时创建临时对象并用 c 来初始化时
  • 对象 d 创建并用函数返回的临时对象初始化时


一般的编译器都可以做到返回值优化(Return Value Optimization, RVO),即直接把返回值建立在函数返回值要初始化或者赋值的对象上(上例中的对象 d)。这个优化的目的是消除函数返回时的临时对象的创建以及拷贝。这样优化之后上面的程序就只有 3 次拷贝了(上表中的 3 被省略,d 变为由 c 直接初始化拷贝),也就是上面书上给出的结果。

在此基础上编译器还可以进行进一步的优化:有名返回值优化(Named Return Value Optimization, NRVO)。NRVO 指的是:如果函数中 return 的对象是一个局部变量且为非 const 或 volatile,编译器可以把这个局部变量(上例中的对象 c)直接建立在函数返回值要初始化或者赋值的对象上(上例中的对象 d)。这样优化之后就只有 2 次对象拷贝操作了(上表中的 3、4 被省略)。

至于这种优化为什么叫“有名”返回值优化,那是因为它优化的对象是函数返回的局部变量,而这个局部变量是有名子的(Named)。与之对应,上面提到的 RVO 是对函数返回临时对象的优化,而这个临时对象是一个无名对象。

论坛徽章:
0
4 [报告]
发表于 2005-08-31 10:54 |只看该作者

C++疑问?关于copy constructor?

强!顶!

论坛徽章:
0
5 [报告]
发表于 2005-08-31 17:06 |只看该作者

C++疑问?关于copy constructor?

根据C++ 标准,上是对的:
default constructor    // 定义变量 X a;
calling userCode()     
copy constructor       // 传递参数,调用 copy constructor;
copy constructor      // 初始化 X c = b;
copy constructor       // 返回参数.
back in main()

但是在具体编译器实现上, 会有所不同.
大多数编译器,会实现一种 NRV 优化.
(1) 未优化时,可能转化为:
X __temp0;
__temp0.X::X(b);             // call copy constructor

void UserCode(X& __result)
{
       X __temp1;
       __temp1.X::X(temp0);     // call copy constructor
      
       __result.X::X(__temp1);  // call copy constructor
      
      return;
}



(2) NRV优化, 可能会被转化为以下C++伪代码

X __temp0;
__temp0.X::X(b);                // 调用一次 copy constructor

void UserCode(X& __result)
{
        __result.X::X(_temp0);  // 对返回值调用 copy constructor
        return;
}


(3) 对于以上例子,更高明的编译甚至可以这样, 转化 C++ 伪代码

X __result;
__result.X::X(b);        // only one copy constructor

void UserCode(void)
{
          return;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP