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


    在一个函数的内部,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;
    }
    
  • 相关阅读:
    Light OJ 1067 Combinations (乘法逆元)
    hdu1172猜数字(暴力枚举)
    hdu 2266 How Many Equations Can You Find(DFS)
    项目之问卷调查问题
    Django之Modelform组件
    GIT
    form组件的总结
    总结django知识点
    djang-分页
    Django-Ajax
  • 原文地址:https://www.cnblogs.com/iyoyos/p/4200546.html
Copyright © 2020-2023  润新知