1、初始化与绑定
指针(Pointer) 可以在声明时不初始化,稍后可以指向不同的对象。引用(Reference)必须在声明时初始化,并且一旦绑定到某个对象,就不能再绑定到其他对象。
#include <iostream>
int main() {
int x = 5;
int y = 10;
// 指针示例
int* p; // 定义一个指向 int 类型的指针
p = &x; // p 指向 x
std::cout << "p points to x: " << *p << std::endl; // 输出 5
p = &y; // p 现在指向 y
std::cout << "p points to y: " << *p << std::endl; // 输出 10
// 引用示例
int& r = x; // r 引用 x
std::cout << "r references x: " << r << std::endl; // 输出 5
// r = &y; // 错误,r 不能重新绑定到其他变量
return 0;
}
2、可空性(Nullability)
指针可以指向 nullptr
,表示不指向任何有效对象,引用 必须引用一个有效的对象,不能为 nullptr
。
#include <iostream>
int main() {
int x = 5;
int* p = nullptr; // p 不指向任何对象
if (p == nullptr) {
std::cout << "p is a null pointer and does not point to any object." << std::endl;
}
// 将 p 指向 x
p = &x;
std::cout << "p now points to x: " << *p << std::endl; // 输出 5
return 0;
}
3、内存地址与大小
指针 是一个独立的变量,拥有自己的内存地址和大小,引用 没有自己的内存地址,其地址和大小与所引用的对象相同。
#include <iostream>
int main() {
// 指针示例
int x = 5;
int* p = &x;
std::cout << "Address of pointer p: " << &p << std::endl; // 输出 p 的地址
std::cout << "Size of pointer p: " << sizeof(p) << " bytes" << std::endl; // 输出指针的大小
// 引用示例
int& r = x;
std::cout << "Address of reference r: " << &r << std::endl; // 输出 x 的地址
std::cout << "Size of reference r: " << sizeof(r) << " bytes" << std::endl; // 输出 x 的大小
return 0;
}
4、数组与多级指针
指针 可以创建指向指针的指针(多级指针),也可以创建指针数组,引用 不能创建指向引用的引用,也不能创建引用数组。
#include <iostream>
int main() {
int x = 5, y = 10;
// 指向指针的指针
int* p = &x; // p 是指向 x 的指针
int** pp = &p; // pp 是指向指针 p 的指针
std::cout << "Address of p: " << &p << std::endl; // 输出 p 的地址
std::cout << "Address stored in pp (which points to p): " << *pp << std::endl; // 输出 pp 存储的 p 的地址
std::cout << "Value of x via pp: " << **pp << std::endl; // 输出 **pp 指向的值,即 x 的值
// 指针数组
int* arr[] = {&x, &y}; // arr 是一个指针数组,元素为 x 和 y 的地址
std::cout << "arr[0] points to x: " << *arr[0] << std::endl; // 输出 arr[0] 指向的值(x 的值)
std::cout << "arr[1] points to y: " << *arr[1] << std::endl; // 输出 arr[1] 指向的值(y 的值)
// 引用示例
int& r = x; // r 是 x 的引用
std::cout << "r references x: " << r << std::endl; // 输出 r 引用的值,即 x 的值
// 错误的代码:
// int&& rr = r; // 错误,不能创建引用的引用
// int& arr[] = {r, s}; // 错误,不能创建引用数组
return 0;
}
5、使用场景
引用 通常用于函数参数和返回类型,提供更简洁的语法,避免不必要的复制。指针 用于动态内存管理、实现复杂数据结构(如链表、树等)以及需要明确控制内存地址的场景。
#include <iostream>
void increment(int& n) {
n++; // 增加 n 的值
}
int main() {
// 使用引用作为函数参数
int num = 5;
std::cout << "Before increment: " << num << std::endl;
increment(num); // 调用函数,传递引用
std::cout << "After increment: " << num << std::endl;
// 动态内存分配和释放
int* p = new int(10); // 动态分配内存并初始化为 10
std::cout << "Dynamically allocated value: " << *p << std::endl;
delete p; // 释放内存
return 0;
}