现在的位置: 首页 > 综合 > 正文

关于函数返回值的几种情况

2017年11月08日 ⁄ 综合 ⁄ 共 2131字 ⁄ 字号 评论关闭

在一个函数的内部,

return

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

 

1.    

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

int a;

a = 5;

return a;

 

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

 

2.    

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

int a[] = {1, 2};

return a;

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

 

3.    

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

int a = new int(5);

return a;

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

 

4.    

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

class A

{

public:

   
          
OtherClass * ...

};

 

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

A a;

return a;

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

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

 

实验代码如下:

#include
<iostream>

using
namespace
std;

int
some_fun1()

{

   
int
a = 5;

   
return
a;                  
//OK

}

 

int
* some_fun2()

{

   
int
a = 5;

   
int
*b = &a;

   
return
b;                  
// not OK

}

 

int
* some_fun3()

{

   
int
*c = new
int
(5);

   
return
c;                  
// OK, return c

执行完后

并没被销毁

必须要用
delete
才能销毁

}

 

class
CSomething

{

public
:

   
int
a;

   
int
b;

 

public
:

   
CSomething(int
a, int
b)

   
{

       
this
->a = a; 

       
this
->b = b;

   
}

};

 

class
CA

{

private
:

   
CSomething* sth;           
//

以指针形式存在的成员变量

                               

public
:

   
CA(CSomething* sth)

   
{

       
this
->sth = new
CSomething(sth->a, sth->b);

   
}

 

   
//

如果不实现深拷贝,请注释这个拷贝构造函数

   
CA(CA& obj)

   
{

        
sth = new
CSomething((obj.sth)->a, (obj.sth)->b);

   
}

 

   
~CA()

   
{

       
cout << "In the destructor of class CA..."
<< endl;

       
if
(NULL != sth) delete
sth;

   
}

   
void
Show()

   
{

       
cout << "("
<< sth->a << ", "
<< sth->b << ")"
<< endl;

   
}

   
void
setValue(int
a, int
b)

   
{

       
sth->a = a;

       
sth->b = b;

   
}

   
void
getSthAddress()

   
{

       
cout << sth << endl;

   
}

};

 

CA some_fun4()

{

   
CSomething c(1, 2);

   
CA a(&c);

   
return
a;                      
//

如果
CA
没有实现深拷贝


not OK

如果实现深拷贝


OK

}

 

int
main(int
argc, char
* argv[])

{

   
int
a = some_fun1();

   
cout << a << endl;             
// OK

 

   
int
*b = some_fun2();

   
cout << *b << endl;            
// not OK


即便返回结果正确

也不过是运气好而已

 

   
int
*c = some_fun3();          
// OK, return c

执行完后

c
并没有被销毁

必须要用
delete
才能销毁

   
cout << *c << endl;

   
delete
c;

 

   
CA d = some_fun4();            
//

如果
CA
没有实现深拷贝


not OK

如果实现深拷贝


OK

   
d.Show();

 

 

   
return
0;

}

抱歉!评论已关闭.