![]() |
#2
love云彩2013-08-16 20:48
|
对于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