函数返回值通常都具有右值属性,在函数的调用者空间根据函数的返回类型创建一个匿名对象,负责接收该函数的返回值,该匿名对象一般是临时对象。如果函数返回的是一个引用,那么用于接收该返回值的就不再是一个临时对象,而是一个引用该函数所返回引用的目标对象的引用,甚至可以是左值引用。
实现此案例需要按照如下步骤进行。
步骤一:返回全局、静态、成员变量的引用
代码如下所示:
#include <iostream> int g = 123; struct Dummy { int m; int& foo (void) { returng; } int& bar (void) { staticint s = 456; return s; } int& hum (void) { returnm; } }; int main(int argc, constchar * argv[]) { Dummy dummy = {789}; int&rg = dummy.foo (); std::cout<<"rg = "<< rg << std::endl; int&rs = dummy.bar (); std::cout<<"rs = "<< rs << std::endl; int&rm = dummy.hum (); std::cout<<"rm = "<< rm << std::endl; return0; }
上述代码中,以下代码:
int& foo (void) { returng; }
定义了结构体Dummy的一个成员函数,该函数返回全局变量g的一个引用。
上述代码中,以下代码:
int&rg = dummy.foo ();
定义了一个引用rg,该引用通过返回引用的函数foo使其成为全局变量g的别名,所以,下述语句:
std::cout<<"rg = "<< rg << std::endl;
输出的是全局变量g的值。
上述代码中,以下代码:
int& bar (void) { staticint s = 456; return s; }
定义了结构体Dummy的一个成员函数,该函数返回静态局部整型变量s的一个引用。
上述代码中,以下代码:
int&rs = dummy.bar ();
定义了一个引用rs,该引用通过返回引用的函数bar使其成为静态局部整型变量s的别名,所以,下述语句:
std::cout<<"rs = "<< rs << std::endl;
输出的是静态局部整型变量s的值。
上述代码中,以下代码:
int& hum (void) { returnm; }
定义了结构体Dummy的一个成员函数,该函数返回结构体成员变量m的一个引用。
上述代码中,以下代码:
int&rm = dummy.hum ();
定义了一个引用rm,该引用通过返回引用的函数hum使其成为机构体成员变量m的别名,所以,下述语句:
std::cout<<"rm = "<< rm << std::endl;
输出的是结构体成员变量m的值。
步骤二:返回调用对象自身的引用
代码如下所示:
#include <iostream> int g = 123; struct Dummy { int m; int& foo (void) { returng; } int& bar (void) { staticint s = 456; return s; } int& hum (void) { returnm; } Dummy& up (void) { ++m; return *this; } }; int main(int argc, constchar * argv[]) { Dummy dummy = {789}; int& rg = dummy.foo (); std::cout<<"rg = "<< rg <<std::endl; int& rs = dummy.bar (); std::cout<<"rs = "<< rs <<std::endl; int& rm = dummy.hum (); std::cout<<"rm = "<< rm <<std::endl; dummy.up().up().up(); std::cout<<"rm = "<< rm <<std::endl; return0; }
上述代码中,以下代码:
Dummy& up (void) { ++m; return *this; }
定义了结构体Dummy的一个成员函数,该函数返回结构体自身*this的一个引用。
上述代码中,以下代码:
dummy.up().up().up();
相当于写成如下方式:
(dummy.up()).up().up();
因为dummy.up()函数的返回值就是dummy自身,所以(dummy.up()).up()在第一个up函数返回后等效于(dummy).up(),依次类推。
步骤三:返回堆变量的引用
代码如下所示:
#include <iostream> int g = 123; struct Dummy { int m; int& foo (void) { returng; } int& bar (void) { staticint s = 456; return s; } int& hum (void) { returnm; } Dummy& up (void) { ++m; return *this; } }; int& square (int x) { int* y = newint; *y = x * x; return *y; } int main(int argc, constchar * argv[]) { Dummy dummy = {789}; int& rg = dummy.foo (); std::cout<<"rg = "<< rg <<std::endl; int& rs = dummy.bar (); std::cout<<"rs = "<< rs <<std::endl; int& rm = dummy.hum (); std::cout<<"rm = "<< rm <<std::endl; dummy.up().up().up(); std::cout<<"rm = "<< rm <<std::endl; int& y = square(16); std::cout<< y <<std::endl; // 256 delete&y; return0; }
上述代码中,以下代码:
int& square (int x) { int* y = newint; *y = x * x; return *y; }
定义了一个返回堆上变量引用的函数,在该函数体中,在堆上申请了一块儿存储空间,并返回该存储空间的引用。
上述代码中,以下代码:
int&y = square(16);
定义了一个引用y,该引用是对上申请的一块儿空间的别名。引用y实质上是一种“野引用”或“悬空引用”。
步骤四:返回引用型参数本身
代码如下所示:
#include <iostream> int g = 123; struct Dummy { int m; int& foo (void) { returng; } int& bar (void) { staticint s = 456; return s; } int& hum (void) { returnm; } Dummy& up (void) { ++m; return *this; } }; int& square (int x) { int* y = newint; *y = x * x; return *y; } intconst& max (intconst& a, intconst& b) { return a > b ? a : b; } int main(int argc, constchar * argv[]) { Dummy dummy = {789}; int& rg = dummy.foo (); std::cout<<"rg = "<< rg <<std::endl; int& rs = dummy.bar (); std::cout<<"rs = "<< rs <<std::endl; int& rm = dummy.hum (); std::cout<<"rm = "<< rm <<std::endl; dummy.up().up().up(); std::cout<<"rm = "<< rm <<std::endl; int& y = square(16); std::cout<< y <<std::endl; // 256 delete&y; int a = 123, b = 456; std::cout<<&a <<' '<<&b <<std::endl; intconst& c = max (a, b); std::cout<<&c <<" : "<< c <<std::endl; return0; }
上述代码中,以下代码:
intconst& max (intconst& a, intconst& b) { return a > b ? a : b; }
定义了一个返回常引用的函数,该函数有两个常引用形参,返回的是大的那个常引用形参。
上述代码中,以下代码:
intconst& c = max (a, b);
定义了一个常引用c,它将是整型变量a或b的别名,至于最终是哪一个变量的别名,取决于哪个整型变量的值大。在本例中,由于a被初始化成了123,b被初始化成了456,b大于a,所以常引用c就是变量b的别名。
步骤五:不能返回局部变量的引用
代码如下所示:
#include <iostream> int g = 123; struct Dummy { int m; int& foo (void) { returng; } int& bar (void) { staticint s = 456; return s; } int& hum (void) { returnm; } Dummy& up (void) { ++m; return *this; } }; int& square (int x) { int* y = newint; *y = x * x; return *y; } intconst& max (intconst& a, intconst& b) { return a > b ? a : b; } int& foo (void) { int n = 123; return n; } int main(int argc, constchar * argv[]) { Dummy dummy = {789}; int& rg = dummy.foo (); std::cout<<"rg = "<< rg <<std::endl; int& rs = dummy.bar (); std::cout<<"rs = "<< rs <<std::endl; int& rm = dummy.hum (); std::cout<<"rm = "<< rm <<std::endl; dummy.up().up().up(); std::cout<<"rm = "<< rm <<std::endl; int& y = square(16); std::cout<< y <<std::endl; // 256 delete&y; int a = 123, b = 456; std::cout<<&a <<' '<<&b <<std::endl; intconst& c = max (a, b); std::cout<<&c <<" : "<< c <<std::endl; int&z = foo(); std::cout<<"z = "<< z <<std::endl; return0; }
上述代码中,以下代码:
int& foo (void) { int n = 123; return n; }
是错误的。因为函数foo返回了局部变量n的引用。由于当函数foo运行结束时,变量n所占的存储空间已经被释放,所以返回的引用就没有一块儿合法的存储空间相对应了,这样必然带来不测的后果。所以下面的代码中:
int&z = foo();
引用z所对应的存储空间是一块儿已经被释放的存储空间,这样使用z将是危险的。
本案例的完整代码如下所示:
#include <iostream> int g = 123; struct Dummy { int m; int& foo (void) { returng; } int& bar (void) { staticint s = 456; return s; } int& hum (void) { returnm; } Dummy& up (void) { ++m; return *this; } }; int& square (int x) { int* y = newint; *y = x * x; return *y; } intconst& max (intconst& a, intconst& b) { return a > b ? a : b; } int& foo (void) { int n = 123; return n; } int main(int argc, constchar * argv[]) { Dummy dummy = {789}; int& rg = dummy.foo (); std::cout<<"rg = "<< rg <<std::endl; int& rs = dummy.bar (); std::cout<<"rs = "<< rs <<std::endl; int& rm = dummy.hum (); std::cout<<"rm = "<< rm <<std::endl; dummy.up().up().up(); std::cout<<"rm = "<< rm <<std::endl; int& y = square(16); std::cout<< y <<std::endl; // 256 delete&y; int a = 123, b = 456; std::cout<<&a <<' '<<&b <<std::endl; intconst& c = max (a, b); std::cout<<&c <<" : "<< c <<std::endl; int&z = foo(); std::cout<<"z = "<< z <<std::endl; return0; }
定义一个用户类User,该类包含两个私有的数据成员,它们是姓名name和年龄age;包含六个公有的成员函数,它们是带参构造函数User,设置姓名函数setName,获取姓名函数getName,设置年龄函数setAge,获取年龄函数getAge,自我介绍函数who。
实现此案例需要按照如下步骤进行。
步骤一:定义用户类
代码如下:
#include <iostream> class User { private: std::string m_name; int m_age; public: User (std::stringconst& name, int age) { m_name = name; m_age = age; } void setName(std::stringconst& name) { m_name = name; } std::string getName() { returnm_name; } void setAge(const int& age) { m_age = age; } int getAge() { returnm_age; } void who (void); }; voidUser::who (void) { std::cout<<"我是"<<m_name<<",今年"<< m_age <<"岁。"<< std::endl; }
上述代码中,以下代码:
class User
定义了一个类,其中class为关键字,表示开始定义一个类;User为标识符,表示类名。
上述代码中,以下代码:
private: std::string m_name; int m_age;
定义了两个私有的数据成员,姓名m_name和年龄m_age。
上述代码中,以下代码:
public: User (std::stringconst& name, int age) { m_name = name; m_age = age; } void setName(std::stringconst& name) { m_name = name; } std::string getName() { returnm_name; } void setAge(const int& age) { m_age = age; } int getAge() { returnm_age; } void who (void);
定义了五个成员函数,它们是带参构造函数User,设置姓名函数setName,获取姓名函数getName,设置年龄函数setAge,获取年龄函数getAge。
声明了一个成员函数,是自我介绍函数who。该函数的定义在类外实现,如以下代码所示:
voidUser::who (void) { std::cout<<"我是"<<m_name<<",今年"<< m_age <<"岁。"<< std::endl; }
在类外定义函数时,注意使用类名加作用域限定符(User::)说明该函数属于哪一个类。
步骤二:将用户类实例化为对象
代码如下所示:
#include <iostream> class User { private: std::string m_name; int m_age; public: User (std::stringconst& name, int age) { m_name = name; m_age = age; } void setName(std::stringconst& name) { m_name = name; } std::string getName() { returnm_name; } void setAge(constint& age) { m_age = age; } int getAge() { returnm_age; } void who (void); }; voidUser::who (void) { std::cout<<"我是"<<m_name<<",今年"<< m_age <<"岁。"<< std::endl; } intmain(int argc, constchar * argv[]) { User user("张飞", 25); user.who(); user.setName("关羽"); user.setAge(28); user.who(); return0; }
上述代码中,以下代码:
User user("张飞", 25);
定义了一个用户类User的对象user。类是用户自定义的一种数据类型,所以可以直接用类名来定义对象。对象名user后面的括号中的内容为类User的构造函数的实参,当为对象user分配完存储空间后将自动调用类的构造函数。
上述代码中,以下代码:
user.who(); user.setName("关羽"); user.setAge(28); user.who();
是调用类的成员函数。
本案例的完整代码如下所示:
#include <iostream> class User { private: std::string m_name; int m_age; public: User (std::stringconst& name, int age) { m_name = name; m_age = age; } void setName(std::stringconst& name) { m_name = name; } std::string getName() { returnm_name; } void setAge(const int& age) { m_age = age; } int getAge() { returnm_age; } void who (void); }; voidUser::who (void) { std::cout<<"我是"<<m_name<<",今年"<< m_age <<"岁。"<< std::endl; } intmain(int argc, constchar * argv[]) { User user("张飞", 25); user.who(); user.setName("关羽"); user.setAge(28); user.who(); return0; }