免费注册 查看新帖 |

Chinaunix

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

[C++] 请问C++的复制构造函数,何时被调用? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-12-06 14:07 |只看该作者 |倒序浏览
  1.       1 #include <iostream>;
  2.       2 using namespace std;
  3.       3
  4.       4 class Point
  5.       5 {
  6.       6 private:
  7.       7         int x;
  8.       8         int y;
  9.       9 public:
  10.      10         int GetX(){return x;}
  11.      11         int GetY(){return y;}
  12.      12         void Assign(int xx=0,int yy=0)
  13.      13         {
  14.      14                 x = xx;
  15.      15                 y = yy;
  16.      16         }
  17.      17
  18.      18         Point(int xx=0,int yy=0)
  19.      19         {
  20.      20                 x = xx;
  21.      21                 y = yy;
  22.      22         }
  23.      23         Point(Point &p)
  24.      24         {
  25.      25                 x = p.x;
  26.      26                 y = p.y;
  27.      27                 cout<<"copy constructor invoked"<<endl;
  28.      28         }
  29.      29 };
  30.      30
  31.      31 Point f(Point p)
  32.      32 {
  33.      33         p.Assign(  2*p.GetX() ,  2*p.GetY()  );
  34.      34
  35.      35         return p;
  36.      36 }
  37.      37
  38.      38 int main(void)
  39.      39 {
  40.      40         Point p1(2,3);
  41.      41         Point p2;
  42.      42         p2 = f(p1);
  43.      43
  44.      44
  45.      45         return 0;
  46.      46 }
复制代码


输出了两次“copy constructor invoked”。第42行p2 = f(p1),倘若把这句注释掉,就没有复制构造函数被调用了。我看书上说,复制构造函数有3种情况被调用:
1, A(B)这样的初始化;
2,象上边f(Point p),调用f()时的形参、实参结合;
3,象上边f(Point p),返回Point型的对象时。

这个小程序符合条款的2和3,所以输出了2次“copy constructor invoked”。似乎是正确的;然而,同样的小程序输出却很不一样:

  1.       1 #include <iostream>;
  2.       2 using namespace std;
  3.       3
  4.       4 class Point
  5.       5 {
  6.       6 private:
  7.       7         int x;
  8.       8         int y;
  9.       9 public:
  10.      10         Point(int xx=0,int yy=0){x=xx;y=yy;}
  11.      11         Point(Point& p1){
  12.      12                 x = p1.x;
  13.      13                 y = p1.y;
  14.      14                 cout<<"copy constructor invoked"<<endl;
  15.      15         }
  16.      16
  17.      17 };
  18.      18
  19.      19 Point f()
  20.      20 {
  21.      21         Point tmp(32,33);
  22.      22         return tmp;
  23.      23 }
  24.      24
  25.      25 int main()
  26.      26 {
  27.      27         Point p1;
  28.      28         p1 = f();
  29.      29         return 0;
  30.      30 }
复制代码


这次没有参数传递,不符合第2条;却还有返回对象,依然符合第3条啊。可是运行时什么输出都没有。

还有,我是在书上看的,书上还为这3种情况各举了一个例子,就跟上面差不多。结果却不一样。我糊涂了,请朋友们帮帮忙吧,谢了谢了先

论坛徽章:
0
2 [报告]
发表于 2004-12-06 14:43 |只看该作者

请问C++的复制构造函数,何时被调用?

是不是问的太菜了?呵呵. 还请朋友们帮忙呀。这个坎儿过不去,让我觉得什么构造、复制构造、析构都一下子不明白起来:-)

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
3 [报告]
发表于 2004-12-06 15:02 |只看该作者

请问C++的复制构造函数,何时被调用?

1>;一点建议:以后帖代码时可否不要把前面的行号带进来?
2>;问题:
void f(T t);会转成:
T _temp;
_temp.T::T(t);  //copy-ctor
f(_temp);

T f( )
{
   T temp;
//处理temp
   return temp;
}
T t=f()会转成编译器把temp用_result取代)
void f(T &_result)
{
      _result.T::T() ;  //default ctor
    //处理_result
} //NRV优化,f中的temp的dtor会在_result作用结束后才会调用.

不能简单的把形式上的差别与结果上的差别直接比较,而要看具体的形式编译器会如何具体的处理,一种形式会优化而另一种完全不会.这还要看如何触发NRV,lippman讲定义了copy-ctor会产生NRV,事实上那是他那个时代的事,现在的编译器都这么先进.这种结果完全看编译器如何优化.

论坛徽章:
0
4 [报告]
发表于 2004-12-06 15:12 |只看该作者

请问C++的复制构造函数,何时被调用?

我的代码没有一次调用copy construtor呀

  1. #include <iostream>;

  2. using namespace std;

  3. class point
  4. {
  5. private:
  6.   int x;
  7.   int y;
  8. public:
  9.   point(int xx = 0, int yy = 0) { x = xx, y =yy; }
  10.   point(point &p1) {
  11.     x = p1.x;y = p1.y;
  12.     cout << "now you are int the copy construtor\n";
  13.   }
  14.   void assign(int xx = 0, int yy =0) { x = xx, y = yy;}
  15.   int getx() { return x; }
  16.   int gety() { return y; }

  17. };

  18. point f()
  19. {
  20.   point tmp(32,44);
  21.   return tmp;
  22. }

  23. point f(point &p1)
  24. {
  25.   p1.assign(p1.getx() * 2, p1.gety() * 2);
  26. }

  27. int main(void)
  28. {
  29.   cout << "test\n";
  30.   point p1(2, 3);
  31.   point p2;
  32.   p2 = f(p1);

  33.   cout << "test code \n";
  34.   point p3;
  35.   p3 = f();
  36.   
  37.   return 0;
  38. }

复制代码

输出结果:
test
test code

论坛徽章:
0
5 [报告]
发表于 2004-12-06 15:17 |只看该作者

请问C++的复制构造函数,何时被调用?

converse你的f(point &p1)当然不算了,你是用传引用,不是传值的啊。

不带参数的那个f(),跟我第2个小程序一样,也是没有输出。THEBEST的话看了半天还没看懂,继续看……

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
6 [报告]
发表于 2004-12-06 15:24 |只看该作者

请问C++的复制构造函数,何时被调用?

如果有兴趣,建议看<<inside the c++ object model>;>;,里面讲了很多底层机制.

论坛徽章:
0
7 [报告]
发表于 2004-12-06 15:27 |只看该作者

请问C++的复制构造函数,何时被调用?

[quote]原帖由 "THEBEST"]如果有兴趣,建议看<<inside the c++ object model>;>;,里面讲了很多底层机制.[/quote 发表:


谢谢!我刚刚搜索了一下NRV和RVO的资料,大体上知道问题出在哪里了,多谢呵呵

论坛徽章:
0
8 [报告]
发表于 2004-12-06 15:44 |只看该作者

请问C++的复制构造函数,何时被调用?

弄个大体明白了,书上讲的没错,编译器做了优化,以至于改变了程序预期的行为,呵呵(这个特性想起来就不舒服)

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
9 [报告]
发表于 2004-12-06 15:51 |只看该作者

请问C++的复制构造函数,何时被调用?

的确如此.有时你也会说编译器好聪明,有时你又说它背着你干些你不知道的事,你叫编译器也难做人.到底该怎么办呢?那就是你的程序形为永远不要依赖于这些优化.

论坛徽章:
0
10 [报告]
发表于 2004-12-06 16:07 |只看该作者

请问C++的复制构造函数,何时被调用?

[quote]原帖由 "THEBEST"]的确如此.有时你也会说编译器好聪明,有时你又说它背着你干些你不知道的事,你叫编译器也难做人.到底该怎么办呢?那就是你的程序形为永远不要依赖于这些优化.[/quote 发表:


赞同!其实平时也是用指针、引用什么的,只是今天看了一个帖子扯到“临时对象”,才想起来试试看这种方式。

对了,再问一下,下面2种声明一个类的对象的方式有不同吗?

  1. Point p1;
  2. p1 = Point(1,3);
复制代码


  1. Point p1=Point(2,3)
复制代码


第2种方式,编译器告诉说no matching function for call to `Point:oint(Point)',说是候选者为构造函数和复制构造函数。

也只是尝试,一般平时都用Point p1(3,3)这样的,呵呵。不过不大明白为什么前面的2种方式一可一不可呢?盼再指点一下~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP