C++ 引用
10. 引用
- References are a new data type in C++;
- Local or global variables
- For ordinary variables, the initial value is required
- In parameter lists and member variables
- Binding defined by caller or constructor
char c; // a character
char* p = &c; // a pointer to a character
char& r = c; // a reference to a character
10.0 变量名回顾
- 变量名实质上是一段连续存储空间的别名,是一个标号(门牌号);
- 程序通过变量来申请并命名内存空间;
- 通过变量的名字可以使用存储空间;
10.1 引用详解
- 引用可以看作是已定义变量的别名
- Declares a new name for an existing object
int X = 47;
int& Y = X; // Y is a reference to X
// X and Y now refer to the same variable
cout << "Y = " << Y << endl;
Y = 18; // 此处,修改 Y 的值,也就是修改 X 的值
cout << "X = " << X << endl;
system("pause");
10.2 引用的规则
- References must be initialized when defined
- 普通引用在声明时,必须用其他的变量进行初始化;
- 引用作为函数参数声明时,不需要初始化;
- Initialization establishes a binding
// In declaration
int x = 3;
int& y = x;
const int& z = x;
// As a function argument
void f(int& x);
f(y); // initialized when function is called
10.3 示例
引用的本质分析:
- 引用在 C++ 的内部实现是一个常量指针
Type& name
等同于Type* const name
#include <iostream>
using namespace std;
int* f(int* x) {
(*x)++;
return x;
}
int& g(int& x) {
x++;
return x;
}
int x;
int& h() {
int q;
return x;
}
int main() {
int a = 0;
f(&a); // Ugly (but explicit)
cout << "f(&a) = " << a << endl;
g(a); // Clean (but hidden)
cout << "g(a) = " << a << endl;
h() = 16;
cout << "h() = " << x << endl;
}
10.3.1 示例2
#include <iostream>
using namespace std;
void myswap(int a, int b)
{
int c;
c = a;
a = b;
b = c;
}
void myswap01(int* a, int* b)
{
int c;
c = *a;
*a = *b;
*b = c;
}
void myswap02(int& a, int& b)
{
int c = 0;
c = a;
a = b;
b = c;
}
int main()
{
int x, y;
x = 10;
y = 20;
myswap(x, y);
cout << "myswap x:" << x << "\ty:" << y << endl;
x = 10;
y = 20;
myswap01(&x, &y);
cout << "myswap01 x:" << x << "\ty:" << y << endl;
x = 10;
y = 20;
myswap02(x, y);
cout << "myswap02 x:" << x << "\ty:" << y << endl;
system("pause");
}
10.4 Pointers vs. References
-
Pointers
- can be set to null
- pointer is independent of existing objects
- can change to point to a different address
-
References
- can't be null
- are dependent on an existing variable, they are an alias for an variable
- can't change to a new "address" location
-
约束
// No references to references
// No pointers to references
int&* p; // illegal
// Reference to pointer is ok
void f(int*& p); // ok
// No arrays of references
10.5 References as class members
- Declared without initial value
- Must be initialized using constructor initializer list
class X {
public:
int& m_y;
X(int& a);
};
X::X(int& a) : m_y(a) { }
10.6 Returning references
- Functions can return references
- But they better refer to non-local variables!
#include <assert.h>
const int SIZE = 32;
double myarray[SIZE];
double& subscript(const int i) {
return myarray[i];
}
- 当函数返回值为引用时
- 若返回栈变量,则不能成为其他引用的初始值,不能作为左值使用;
- 若返回静态变量或全局变量,可以成为其他引用的初始值,既可作为右值使用,也可作为左值使用;
- 示例01:返回栈变量
#include "iostream"
using namespace std;
int getResult()
{
int a;
a = 10;
return a;
}
int& getResult01()
{
int a; // 如果返回栈上的引用,有可能会有问题。
a = 10;
return a;
}
int* getResult02()
{
int a;
a = 10;
return &a;
}
int main()
{
int a1 = 0;
int a2 = 0;
a1 = getResult();
cout << "a1: " << a1 << endl;
a2 = getResult01();
cout << "a2: " << a2 << endl;
int &a3 = getResult01();
cout << "a3: " << a3 << endl;
getchar();
return 0;
}
- 示例02:返回静态变量
int& getResult05()
{
static int a = 10;
a++;
return a;
}
int main()
{
int a2 = getResult05();
cout << "a2: " << a2 << endl;
int &a3 = getResult05();
cout << "a3: " << a3 << endl;
getchar();
return 0;
}
- 示例03:函数返回值为引用,当左值
// g() 返回变量的值
int g()
{
static int a = 10;
a++;
return a;
}
// g2() 返回变量本身,即返回变量所标识的内存空间
int& g2()
{
static int a = 11;
a++;
cout << "g2() a:" << a << endl;
return a;
}
int main()
{
// 解释:g() 返回的结果为 10,下面的表达式等同于:10 = 100,故不成立
// g() = 100;
// 解释:g2() 返回的结果为 a,下面的表达式等同于:a = 100, 故成立
g2() = 100; // 函数返回值为引用,当左值
g2(); // 此时,结果输出 a: 101
int c = g2();
getchar();
return 0;
}
10.7 const in Functions Arguments
- Pass by const value -- don't do it
- Passing by const reference:
Person (const string& name, int weight);
- don't change the string object
- more efficient to pass by reference(address) than to pass by value(copy)
- const qualifier protects from change
10.8 Temporary values are const
- 示例:
#include <iostream>
using namespace std;
void f(cosnt int& i)
{
cout << i << endl;
}
int main()
{
int i = 3;
f(i * 3);
return 0;
}
- 错误示例:
void func(int&);
func(i * 3); // Generates error!
// 实际编译结果:
void func(int&);
const int temp@ = i * 3;
func(temp@); // Problem -- binding const ref to non-const argument!
// The temporary is constant, since you can't access it.
10.9 const in Function returns
- return by const value
- For user defined types, it means "prevent use as an lvalue"
- for built-in's it means nothing
- return by const pointer or reference
- depends on what you want your client to do with the return value
参考链接: