函数返回值的几种情况

末蓝、 2022-06-13 10:40 262阅读 0赞

在一个函数的内部,return的时候返回的都是一个拷贝,不管是变量、对象还是指针都是返回拷贝,但是这个拷贝是浅拷贝。

  1. 如果返回一个基本类型的变量,比如:

int a;

a = 5;

return a;

那么就会a的一个拷贝,即5返回,然后a就被销毁了。尽管a被销毁了,但它的副本5还是成功地返回了,所以这样做没有问题。

  1. 但是对于非动态分配(new/malloc)得到的指针,像1那么做就会有问题,比如在某个函数内部:

int a[] = {1, 2};

return a;

那么也会返回指针a的一个拷贝,我们假定a的地址值为0x002345FC,那么这个0x2345FC是能够成功返回的。当return执行完成后,a就要被销毁,也就是0x002345FC所指向的内存被回收了。如果这时候在函数外面,去地址0x002345FC取值,那得到的结果肯定是不对的。这就是为什么不能返回局部指针的原因。返回局部变量的引用的道理和这个类似。

  1. 对于返回(动态分配得到的)指针的另外一种情况,比如在函数内部:

int a = new int(5);

return a;

这样做是可以的。return a执行完后,a并没有被销毁(必须要用delete才能销毁a),所以这里返回的a是有效的。

  1. 如果不是基本数据类型,比如:

class A

{

public:

  1. OtherClass \* ...

};

如果在某个函数内部有一个A类的局部变量,比如:

A a;

return a;

这时候也会返回a的一个拷贝,如果A没有写深拷贝构造函数,就会调用缺省的拷贝构造函数(浅拷贝),这样做就会失败的;

如果A中提供了深拷贝构造函数,则这样做就是可以的。

实验代码如下:

  1. #include <iostream>
  2. using namespace std;
  3. int some_fun1()
  4. {
  5. int a = 5;
  6. return a; //OK
  7. }
  8. int* some_fun2()
  9. {
  10. int a = 5;
  11. int *b = &a;
  12. return b; // not OK
  13. }
  14. int* some_fun3()
  15. {
  16. int *c = new int(5);
  17. return c; // OK, return c执行完后,并没被销毁(必须要用delete才能销毁)
  18. }
  19. class CSomething
  20. {
  21. public:
  22. int a;
  23. int b;
  24. public:
  25. CSomething(int a, int b)
  26. {
  27. this->a = a;
  28. this->b = b;
  29. }
  30. };
  31. class CA
  32. {
  33. private:
  34. CSomething* sth; // 以指针形式存在的成员变量
  35. public:
  36. CA(CSomething* sth)
  37. {
  38. this->sth = new CSomething(sth->a, sth->b);
  39. }
  40. // 如果不实现深拷贝,请注释这个拷贝构造函数
  41. CA(CA& obj)
  42. {
  43. sth = new CSomething((obj.sth)->a, (obj.sth)->b);
  44. }
  45. ~CA()
  46. {
  47. cout << "In the destructor of class CA..." << endl;
  48. if (NULL != sth) delete sth;
  49. }
  50. void Show()
  51. {
  52. cout << "(" << sth->a << ", " << sth->b << ")" << endl;
  53. }
  54. void setValue(int a, int b)
  55. {
  56. sth->a = a;
  57. sth->b = b;
  58. }
  59. void getSthAddress()
  60. {
  61. cout << sth << endl;
  62. }
  63. };
  64. CA some_fun4()
  65. {
  66. CSomething c(1, 2);
  67. CA a(&c);
  68. return a; // 如果CA没有实现深拷贝,则not OK;如果实现深拷贝,则OK
  69. }
  70. int main(int argc, char* argv[])
  71. {
  72. int a = some_fun1();
  73. cout << a << endl; // OK
  74. int *b = some_fun2();
  75. cout << *b << endl; // not OK,即便返回结果正确,也不过是运气好而已
  76. int *c = some_fun3(); // OK, return c执行完后,c并没有被销毁(必须要用delete才能销毁)
  77. cout << *c << endl;
  78. delete c;
  79. CA d = some_fun4(); // 如果CA没有实现深拷贝,则not OK;如果实现深拷贝,则OK
  80. d.Show();
  81. return 0;
  82. }

转载地址: http://patmusing.blog.163.com/blog/static/13583496020113191407531/

发表评论

表情:
评论列表 (有 0 条评论,262人围观)

还没有评论,来说两句吧...

相关阅读

    相关 OnTrigger情况

    在Unity中,OnTrigger是一种用于处理碰撞事件的函数。它通常用于监测对象之间的触发器(Collider)交互,并在特定的情况下触发相应的逻辑。在Unity中,有以下几

    相关 函数返回是引用情况

    (1) 函数返回值为引用时,若返回栈变量,不能成为其它引用的初始值,不能作为左值    (2) 函数返回值为引用时,若返回的是静态变量或者全局变量,可以成为其他引用的初始值

    相关 函数返回情况

    在一个函数的内部,return的时候返回的都是一个拷贝,不管是变量、对象还是指针都是返回拷贝,但是这个拷贝是浅拷贝。   1.     如果返回一个基本类型的变量,比如:

    相关 JavaScript函数返回

    函数的返回值 > 当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值