可能的返回模式如下;
T X::f(); //按值返回T
T* X::f() //返回T类对象的指针/地址
const T* X::f() //返回const T类对象的指针/地址
T& X::f() //返回T类对象的引用
const T& X::f() // 返回对const T类对象的引用
注意以下5点:
(1)绝不要返回局部变量的引用(或指向局部变量的指针)。函数内部新申请的临时变量(而不是类的数据成员)一旦离开函数即将被销毁,但在此之后 ,引用(或指针)依然存在,它依旧引用(或指向)某些已经不存在的对象。(意味着野指针。。。
(2)如果在函数内部创建新对象,并且希望该对象的所有权移交给主调函数,那么该函数必须返回一个指针。
因为主调函数拥有返回的指针所指向的内存。
比如
class TPerson{
public:
//...
char* CreateNameOfPerson() const;
};
如上TPerson类的成员函数CreateNameOfPerson(),它用于为名称中的字符分配内存,且返回指向该字符的指针(由主调函数所拥有)。当不再需要它时,主调函数应释放内存。只有在指针返回值时,才能转移动态对象的所有权。
void g(){
X x_;
char *tmp_;
tmp_ = new char[initSize];
tmp_ = x_.CreateNameOfPerson();
delete [] tmp_;
delete [] x_.CreateNameOfPerson();
}
(3)如果不允许主调函数修改返回的指针所指向的字符(或者对象),则返回指向const的指针。
class TPerson{
public:
//...
const char* GetNameOfPerson() const;
};
用const限定后内存所有权就不能从被调函数转移到主调函数了。主调函数只能读取返回的指针所指向的内存单元但是不能修改也不能删除它。如果删除,编译器会报错。
对于const函数(不管是不是成员函数),其函数返回值最好都是const限定的,否则会产生矛盾,编译器会检测到错误。
当按值返回的开销很大的时候,推荐使用返回指向const的指针(指向一个数据成员),但是主调函数不应该修改指针所指向的数据内容。(内容包括其值和其型)
注意:绝不要返回指向某个数据成员的非const指针。破坏数据封装,数据本身的值也没法保证。
(4)如果要返回一个基本类型(char int long等) 那么按值返回和按引用返回较为安全和容易,而且易于理解。
(5)在某些情况下,比如操作符重载(operator+),无法返回引用。因为函数的结果未知,正确的实现是按值返回(在函数内部创建一个临时变量)
reference:
Kayshav Dattatri C++:Effective Object-Oriented Software Construction(2nd Edition)