函数返回值通常都具有右值属性,在函数的调用者空间根据函数的返回类型创建一个匿名对象,负责接收该函数的返回值,该匿名对象一般是临时对象。如果函数返回的是一个引用,那么用于接收该返回值的就不再是一个临时对象,而是一个引用该函数所返回引用的目标对象的引用,甚至可以是左值引用。
实现此案例需要按照如下步骤进行。
步骤一:返回全局、静态、成员变量的引用
代码如下所示:
#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;
}