| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 685 人关注过本帖
标题:关于“函数能否返回局部对象或变量的引用和指针”
只看楼主 加入收藏
kervin007
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2013-8-16
结帖率:0
收藏
已结贴  问题点数:20 回复次数:1 
关于“函数能否返回局部对象或变量的引用和指针”
作为一个初学者,对与C++函数的传参和返回值一直比较头疼,这一点就没有Java简单,Java中只有引用传参,返回值也是引用(Java的返回值是否全是引用或其他也没明白,对于Java而言,对搞明白返回值具体是啥貌似没有意义)。
对于C++而言,就要灵活的多,而且也复杂的多。函数的参数有三种传参形式,分别是值传递,引用传递和指针传递,而返回值也有三种,返回引用,指针和值。
看到书上和其他地方说,“函数千万不要返回局部对象或变量的引用和指针”,今天就实地验证了一下。下面这个例子是关于向量加法。前四种方法是将结果也作为参数;后四种方法没有将结果作为参数,而是在函数体内部一定了一个局部变量,然后将此局部变量以引用或者指针的形式作为函数的返回值。这八种方法中有的是以指针为参数,有的是以引用为参数。
有人指出如果函数返回的是局部变量的引用或指针的话,变量所指向的地址在多次运行之后,就会发生改变,所以这里将每种方法的运行结果都运行9次。最后的实测结果是,这八种函数都能顺利通过编译器,而且每一种方法的9次运行结果都是一样的,变量所指向的地址和变量的值都没有改变。
本来这个不是个什么问题,在编写3D数学支持库时,需要用到大量的二元甚至三元变量之间的计算,例如计算向量、矩阵和四元数等相关操作。如果能将计算结果作为返回值返回,而不需要将结果作为函数的参数,这样做,无疑就可以减少一个参数,使得函数看着也清晰易懂。因此就有了“函数返回局部对象或变量的引用和指针的问题”。
各位大大看下是否可以这样做(按照后四种少一个参数的做法)?不吝赐教!
程序代码:
/*

 * test.cpp

 *

 *  Created on: 2013-8-16

 *      Author: xiaohun

 */
#include <iostream>

using namespace std ;

class Vector3D {
public:
    float x,y,z;
public:
    Vector3D(){
        x=y=z=0;
    };
    Vector3D(float x,float y,float z){
        this->x=x;this->y=y;this->z=z;
    };
    void print(char* v);
    static Vector3D& Add1(Vector3D& v1,Vector3D& v2,Vector3D& v);
    static Vector3D& Add2(Vector3D* v1,Vector3D* v2,Vector3D* v);
    static Vector3D* Add3(Vector3D& v1,Vector3D& v2,Vector3D& v);
    static Vector3D* Add4(Vector3D* v1,Vector3D* v2,Vector3D* v);
    static Vector3D& Add5(Vector3D& v1,Vector3D& v2);
    static Vector3D& Add6(Vector3D* v1,Vector3D* v2);
    static Vector3D* Add7(Vector3D& v1,Vector3D& v2);
    static Vector3D* Add8(Vector3D* v1,Vector3D* v2);
};
/**

 * 返回输出变量的引用,输入参数和输出参数都为引用

 */
Vector3D& Vector3D::Add1(Vector3D& v1,Vector3D& v2,Vector3D& v){
    v.x=v1.x+v2.x;
    v.y=v1.y+v2.y;
    v.z=v1.z+v2.z;
    return v;
}
/**

 * 返回输出变量的引用,输入参数和输出参数都为指针

 */
Vector3D& Vector3D::Add2(Vector3D* v1,Vector3D* v2,Vector3D* v){
    v->x=v1->x+v2->x;
    v->y=v1->y+v2->y;
    v->z=v1->z+v2->z;
    return *v;
}
/**

 * 返回输出变量的指针,输入参数和输出参数都为引用

 */
Vector3D* Vector3D::Add3(Vector3D& v1,Vector3D& v2,Vector3D& v){
    v.x=v1.x+v2.x;
    v.y=v1.y+v2.y;
    v.z=v1.z+v2.z;
    return &v;
}
/**

 * 返回输出变量的指针,输入参数和输出参数都为指针

 */
Vector3D* Vector3D::Add4(Vector3D* v1,Vector3D* v2,Vector3D* v){
    v->x=v1->x+v2->x;
    v->y=v1->y+v2->y;
    v->z=v1->z+v2->z;
    return v;
}
/**

 * 返回局部变量的引用(局部变量的引用作为输出),输入参数为引用,没有输出参数

 */
Vector3D& Vector3D::Add5(Vector3D& v1,Vector3D& v2){
    Vector3D* v=new Vector3D();
    v->x=v1.x+v2.x;
    v->y=v1.y+v2.y;
    v->z=v1.z+v2.z;
    return *v;
}
/**

 * 返回局部变量的引用(局部变量的引用作为输出),输入参数为指针,没有输出参数

 */
Vector3D& Vector3D::Add6(Vector3D* v1,Vector3D* v2){
    Vector3D* v=new Vector3D();
    v->x=v1->x+v2->x;
    v->y=v1->y+v2->y;
    v->z=v1->z+v2->z;
    return *v;
}
/**

 * 返回局部变量的指针(局部变量的指针作为输出),输入参数为引用,没有输出参数

 */
Vector3D* Vector3D::Add7(Vector3D& v1,Vector3D& v2){
    Vector3D* v=new Vector3D();
    v->x=v1.x+v2.x;
    v->y=v1.y+v2.y;
    v->z=v1.z+v2.z;
    return v;
}
/**

 * 返回局部变量的指针(局部变量的指针作为输出),输入参数为指针,没有输出参数

 */
Vector3D* Vector3D::Add8(Vector3D* v1,Vector3D* v2){
    Vector3D* v=new Vector3D();
    v->x=v1->x+v2->x;
    v->y=v1->y+v2->y;
    v->z=v1->z+v2->z;
    return v;
}
void Vector3D::print(char* v){
    for(int i=0;i<=8;i++){
        cout<<""<<i+1<<"次v=("<<this->x<<","<<this->y<<","<<this->z<<")"<<this<<endl;
    }
}

/**

 * 返回输出变量的引用,输入参数和输出参数都为引用

 */
void func1(){
    cout<<"返回输出变量的引用,输入参数和输出参数都为引用"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D v;
    Vector3D::Add1(v1,v2,v);
    v.print("v");
}

/**

 * 返回输出变量的引用,输入参数和输出参数都为指针

 */
void func2(){
    cout<<"返回输出变量的引用,输入参数和输出参数都为指针"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D v;
    Vector3D::Add2(&v1,&v2,&v);
    v.print("v");
}
/**

 * 返回输出变量的指针,输入参数和输出参数都为引用

 */
void func3(){
    cout<<"返回输出变量的指针,输入参数和输出参数都为引用"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D v;
    Vector3D::Add3(v1,v2,v);
    v.print("v");
}
/**

 * 返回输出变量的指针,输入参数和输出参数都为指针

 */
void func4(){
    cout<<"返回输出变量的指针,输入参数和输出参数都为指针"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D v;
    Vector3D::Add4(&v1,&v2,&v);
    v.print("v");
}
/**

 * 返回局部变量的引用(局部变量的引用作为输出),输入参数为引用,没有输出参数

 */
void func5(){
    cout<<"返回局部变量的引用(局部变量的引用作为输出),输入参数为引用,没有输出参数"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D v;
    v=Vector3D::Add5(v1,v2);
    v.print("v");
}
/**

 * 返回局部变量的引用(局部变量的引用作为输出),输入参数为指针,没有输出参数

 */
void func6(){
    cout<<"返回局部变量的引用(局部变量的引用作为输出),输入参数为指针,没有输出参数"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D v;
    v=Vector3D::Add6(&v1,&v2);
    v.print("v");
}
/**

 * 返回局部变量的指针(局部变量的指针作为输出),输入参数为引用,没有输出参数

 */
void func7(){
    cout<<"返回局部变量的指针(局部变量的指针作为输出),输入参数为引用,没有输出参数"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D* v=new Vector3D();
    v=Vector3D::Add7(v1,v2);
    v->print("v");
}
/**

 * 返回局部变量的指针(局部变量的指针作为输出),输入参数为指针,没有输出参数

 */
void func8(){
    cout<<"返回局部变量的指针(局部变量的指针作为输出),输入参数为指针,没有输出参数"<<endl;
    Vector3D v1(2,3,4);
    Vector3D v2(1,2,3);
    Vector3D* v=new Vector3D();
    v=Vector3D::Add8(&v1,&v2);
    v->print("v");
}

int main(){
    func1();
    func2();
    func3();
    func4();
    func5();
    func6();
    func7();
    func8();
    return 0;
}

结果如下:
返回输出变量的引用,输入参数和输出参数都为引用
第1次v=(3,5,7)0x22ff20
第2次v=(3,5,7)0x22ff20
第3次v=(3,5,7)0x22ff20
第4次v=(3,5,7)0x22ff20
第5次v=(3,5,7)0x22ff20
第6次v=(3,5,7)0x22ff20
第7次v=(3,5,7)0x22ff20
第8次v=(3,5,7)0x22ff20
第9次v=(3,5,7)0x22ff20
返回输出变量的引用,输入参数和输出参数都为指针
第1次v=(3,5,7)0x22ff20
第2次v=(3,5,7)0x22ff20
第3次v=(3,5,7)0x22ff20
第4次v=(3,5,7)0x22ff20
第5次v=(3,5,7)0x22ff20
第6次v=(3,5,7)0x22ff20
第7次v=(3,5,7)0x22ff20
第8次v=(3,5,7)0x22ff20
第9次v=(3,5,7)0x22ff20
返回输出变量的指针,输入参数和输出参数都为引用
第1次v=(3,5,7)0x22ff20
第2次v=(3,5,7)0x22ff20
第3次v=(3,5,7)0x22ff20
第4次v=(3,5,7)0x22ff20
第5次v=(3,5,7)0x22ff20
第6次v=(3,5,7)0x22ff20
第7次v=(3,5,7)0x22ff20
第8次v=(3,5,7)0x22ff20
第9次v=(3,5,7)0x22ff20
返回输出变量的指针,输入参数和输出参数都为指针
第1次v=(3,5,7)0x22ff20
第2次v=(3,5,7)0x22ff20
第3次v=(3,5,7)0x22ff20
第4次v=(3,5,7)0x22ff20
第5次v=(3,5,7)0x22ff20
第6次v=(3,5,7)0x22ff20
第7次v=(3,5,7)0x22ff20
第8次v=(3,5,7)0x22ff20
第9次v=(3,5,7)0x22ff20
返回局部变量的引用(局部变量的引用作为输出),输入参数为引用,没有输出参数
第1次v=(3,5,7)0x22ff20
第2次v=(3,5,7)0x22ff20
第3次v=(3,5,7)0x22ff20
第4次v=(3,5,7)0x22ff20
第5次v=(3,5,7)0x22ff20
第6次v=(3,5,7)0x22ff20
第7次v=(3,5,7)0x22ff20
第8次v=(3,5,7)0x22ff20
第9次v=(3,5,7)0x22ff20
返回局部变量的引用(局部变量的引用作为输出),输入参数为指针,没有输出参数
第1次v=(3,5,7)0x22ff20
第2次v=(3,5,7)0x22ff20
第3次v=(3,5,7)0x22ff20
第4次v=(3,5,7)0x22ff20
第5次v=(3,5,7)0x22ff20
第6次v=(3,5,7)0x22ff20
第7次v=(3,5,7)0x22ff20
第8次v=(3,5,7)0x22ff20
第9次v=(3,5,7)0x22ff20
返回局部变量的指针(局部变量的指针作为输出),输入参数为引用,没有输出参数
第1次v=(3,5,7)0x3e2cc0
第2次v=(3,5,7)0x3e2cc0
第3次v=(3,5,7)0x3e2cc0
第4次v=(3,5,7)0x3e2cc0
第5次v=(3,5,7)0x3e2cc0
第6次v=(3,5,7)0x3e2cc0
第7次v=(3,5,7)0x3e2cc0
第8次v=(3,5,7)0x3e2cc0
第9次v=(3,5,7)0x3e2cc0
返回局部变量的指针(局部变量的指针作为输出),输入参数为指针,没有输出参数
第1次v=(3,5,7)0x3e2cf0
第2次v=(3,5,7)0x3e2cf0
第3次v=(3,5,7)0x3e2cf0
第4次v=(3,5,7)0x3e2cf0
第5次v=(3,5,7)0x3e2cf0
第6次v=(3,5,7)0x3e2cf0
第7次v=(3,5,7)0x3e2cf0
第8次v=(3,5,7)0x3e2cf0
第9次v=(3,5,7)0x3e2cf0
搜索更多相关主题的帖子: Java 而且 
2013-08-16 20:24
love云彩
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:青藏高原
等 级:贵宾
威 望:53
帖 子:3663
专家分:11416
注 册:2012-11-17
收藏
得分:20 
程序代码:
//可以返回一个引用或者一个指针,同样可以返回一个临时对象,下面是一个返回一个引用的例子
#include<iostream>
using namespace std;
float temp;
float& f(float r)
{
    temp=r*r*3.14;
    return temp;
}
void main()
{
    float &d=f(5.0);
    cout<<d<<endl;
}

思考赐予新生,时间在于定义
2013-08-16 20:48
快速回复:关于“函数能否返回局部对象或变量的引用和指针”
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024770 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved