[关闭]
@lishuhuakai 2015-05-21T09:40:01.000000Z 字数 2215 阅读 1398

c++临时对象

c++


什么是临时对象?

C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象。

实践

下面是一个例子:

  1. #include <iostream>
  2. using namespace std;
  3. class foo
  4. {
  5. public:
  6. foo()
  7. {
  8. cout << "foo构造函数" << endl;
  9. printf("addr = %x\n", this);
  10. }
  11. ~foo()
  12. {
  13. cout << "foo析构函数" << endl;
  14. printf("addr = %x\n", this);
  15. }
  16. };
  17. void main()
  18. {
  19. foo();
  20. printf("Hello,Demo!\n");
  21. system("pause");
  22. }
  23. /**
  24. foo构造函数
  25. addr = 37f9fb
  26. foo析构函数
  27. addr = 37f9fb
  28. Hello,Demo!
  29. */

直接调用foo类的构造函数就会生成一个临时对象,它昙花一现,立马析构。这也说明了这个临时变量既不在堆上,也不再栈上,在哪里,我不知道。

  1. #include <iostream>
  2. using namespace std;
  3. class foo
  4. {
  5. public:
  6. foo()
  7. {
  8. cout << "foo构造函数" << endl;
  9. cout << "addr = " << this << endl;
  10. }
  11. ~foo()
  12. {
  13. cout << "foo析构函数" << endl;
  14. cout << "addr = " << this << endl;
  15. }
  16. foo(const foo &op)
  17. {
  18. cout << "foo拷贝析构函数" << endl;
  19. cout << "addr = " << this << endl;
  20. }
  21. };
  22. void play()
  23. {
  24. foo f = foo();
  25. cout << "&f = " << &f << endl;
  26. printf("Hello,Demo!\n");
  27. }
  28. void main()
  29. {
  30. play();
  31. system("pause");
  32. }
  33. /**
  34. foo构造函数
  35. addr = 002EFA1F
  36. &f = 002EFA1F
  37. Hello,Demo!
  38. foo析构函数
  39. addr = 002EFA1F
  40. */

我们看到,fooo f = foo()这一句,并没有和预计的一样调用拷贝构造函数,很显然,c++在这里做了优化,c++直接将f和构造的临时变量绑定在了一起,因为他们的地址是一致的。这样做的好处是节省了一次构造和析构函数,提升了效率。
这样的话,之前困扰我的问题也很好理解了。

  1. #include <iostream>
  2. using namespace std;
  3. class foo
  4. {
  5. public:
  6. foo()
  7. {
  8. cout << "foo构造函数" << endl;
  9. cout << "addr = " << this << endl;
  10. }
  11. ~foo()
  12. {
  13. cout << "foo析构函数" << endl;
  14. cout << "addr = " << this << endl;
  15. }
  16. foo(const foo &op)
  17. {
  18. cout << "foo拷贝析构函数" << endl;
  19. cout << "addr = " << this << endl;
  20. }
  21. };
  22. foo run()
  23. {
  24. foo a;
  25. return a;
  26. }
  27. void play()
  28. {
  29. foo f = run();
  30. cout << "&f = " << &f << endl;
  31. printf("Hello,Demo!\n");
  32. }
  33. void main()
  34. {
  35. play();
  36. system("pause");
  37. }
  38. /**
  39. foo构造函数
  40. addr = 001CF8EB
  41. foo拷贝析构函数
  42. addr = 001CF9DF
  43. foo析构函数
  44. addr = 001CF8EB
  45. &f = 001CF9DF
  46. Hello,Demo!
  47. foo析构函数
  48. addr = 001CF9DF
  49. */

run函数里定义了一个类的实体a,他返回一个foo类的对象,因为函数返回时会清空栈里的东西,因此c++会构建一个临时的变量返回,此时在play函数里有foo f = run(),这种情况和前面的类似,该临时变量和f绑定起来,提升了效率。
同理,在play函数里我们这么改动,结果是这样的:

  1. #include <iostream>
  2. using namespace std;
  3. class foo
  4. {
  5. public:
  6. foo()
  7. {
  8. cout << "foo构造函数" << endl;
  9. cout << "addr = " << this << endl;
  10. }
  11. ~foo()
  12. {
  13. cout << "foo析构函数" << endl;
  14. cout << "addr = " << this << endl;
  15. }
  16. foo(const foo &op)
  17. {
  18. cout << "foo拷贝析构函数" << endl;
  19. cout << "addr = " << this << endl;
  20. }
  21. void operator = (const foo &op)
  22. {
  23. cout << "=操作" << endl;
  24. cout << "addr = " << this << endl;
  25. }
  26. };
  27. foo run()
  28. {
  29. foo a;
  30. return a;
  31. }
  32. void play()
  33. {
  34. foo f;
  35. f = run();
  36. cout << "&f = " << &f << endl;
  37. printf("Hello,Demo!\n");
  38. }
  39. void main()
  40. {
  41. play();
  42. system("pause");
  43. }
  44. /**
  45. foo构造函数
  46. addr = 004FF797
  47. foo构造函数
  48. addr = 004FF68F
  49. foo拷贝析构函数
  50. addr = 004FF6CB
  51. foo析构函数
  52. addr = 004FF68F
  53. =操作
  54. addr = 004FF797
  55. foo析构函数
  56. addr = 004FF6CB
  57. &f = 004FF797
  58. Hello,Demo!
  59. foo析构函数
  60. addr = 004FF797
  61. */

run函数返回了一个临时对象,foo f; f = run();这一句自然会调用=操作,然后临时变量立刻析构掉。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注