指针定义

数据类型 *指针名; 定义的时候赋初始值,避免野指针

int* p = nullptr;
//int* p = NULL;
//int* p = 0;
cout << "所占存储:" << sizeof(p) << endl;
cout << "地址:" << p << endl;

指针操作符

操作符 名称 作用
& 取地址符 获取变量的内存地址
* 解引用符 访问指针所指向的内存中的值
int* p = nullptr;
int a = 10;
cout << "step1, a=" << a << " ; &a=" << &a << " ; p=" << p << endl;

// p存放变量a的地址
p = &a;
cout << "step2, a=" << a << " ; &a=" << &a << " ; p=" << p << " ; *p=" << *p << endl;

const指针

数据不可变

const int* p,指向常量数据的指针(数据不可改)

int a = 10, b = 10, c = 20;

const int* p = &a;
cout << "p=" << p << ", *p=" << *p << endl;

p = &b;
cout << "p=" << p << ", *p=" << *p << endl;

p = &c;
cout << "p=" << p << ", *p=" << *p << endl;

// 修改报错
// *p = 100;  
cout << c << endl;
cout << "p=" << p << ", *p=" << *p << endl;

c = 100;
cout << c << endl;
cout << "p=" << p << ", *p=" << *p << endl;

地址不可变

int* const p,常量指针(地址不可改)

int a = 10, b = 10, c = 20;

int* const p = &a;
cout << "p=" << p << ", *p=" << *p << endl;

// 报错,地址不能变
// p = &b;
cout << "p=" << p << ", *p=" << *p << endl;

// 修改报错
*p = 100;
cout << c << endl;
cout << "p=" << p << ", *p=" << *p << endl;

c = 100;
cout << c << endl;
cout << "p=" << p << ", *p=" << *p << endl;

地址、数据都不可变

const int* const p,两者皆不可改

int a = 10, b = 10, c = 20;

const int* const p = &a;
cout << "p=" << p << ", *p=" << *p << endl;

// 修改报错
//p = &b;
cout << "p=" << p << ", *p=" << *p << endl;

// 修改报错
//*p = 100;

指针与数组

1、int *p = a;int *p = &a[0];

int a[] = { 1, 2, 3, 4, 5 };
int* p = a;
//int* p = &a[0];

cout << "*p= " << *p << endl;
cout << "*(p+1)= " << *(p + 1) << endl;
cout << "p[2]= " << p[2] << endl;

指针与函数

void swap(int* a, int* b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}

int main()
{
	int a = 10, b = 20;
	cout << "交换前:a=" << a << " , &a=" << &a << endl;
	cout << "交换前:b=" << b << " , &b=" << &b << endl;

	swap(&a, &b);

	cout << "交换后:a=" << a << " , &a=" << &a << endl;
	cout << "交换后:b=" << b << " , &b=" << &b << endl;
}

指针与内存管理

1、 栈上定义的变量不用手动释放,作用域结束就自动回收了
2、堆上定义的变量必须手动delete

分配内存

new关键字

// 在堆分配一个int
int* p = new int;
*p = 42;
cout << "p= " << p << ", *p=" << *p << endl;

释放内存

delete关键字
delete p; // 释放单个对象
delete[] arr; // 释放数组

// 在堆分配一个int
int* p = new int;
*p = 42;
cout << "p= " << p << ", *p=" << *p << endl;

delete p;
p = nullptr;

cout << "p= " << p << ", *p=" << *p << endl;

引用

引用定义的时候必须初始化,一经绑定不可修改,
理解为变量的别名
类似指针常量,地址不可变

特性 引用(Reference) 指针(Pointer)
本质 变量的别名 存储地址的变量
初始化 必须在声明时初始化 可以延迟初始化
重新绑定 ❌ 不能重新绑定 ✅ 可以指向不同对象
空值 ❌ 不存在空引用 ✅ 可以为空(nullptr
内存占用 通常不额外占用(编译器优化) 占用内存(存储地址)
操作符 &(声明时) &(取地址),*(解引用)
int a = 10;
int& ref = a;
cout << "step1, a=" << a << ", ref=" << ref << "&a=" << &a << ", &ref=" << &ref << endl;

a = 20;
cout << "step2, a=" << a << ", ref=" << ref << "&a=" << &a << ", &ref=" << &ref << endl;

ref = 30;
cout << "step3, a=" << a << ", ref=" << ref << "&a=" << &a << ", &ref=" << &ref << endl;

引用作为函数入参

void swap(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}

int main()
{
	int a = 10, b = 20;
	cout << "交换前,a=" << a << ", b=" << b << endl;

	swap(a, b);

	cout << "交换后,a=" << a << ", b=" << b << endl;
}

引用作为函数出参

int& max(int& a, int& b)
{
	return a > b ? a : b;
}
int main()
{
	int a = 10, b = 20;
	cout << "交换前,a=" << a << ", b=" << b << endl;

	// 返回引用, c与b其实是一个地址
	int& c = max(a, b);

	cout << "交换后,a=" << a << ", b=" << b << ", c=" << c << endl;
	cout << "交换后,&a=" << &a << ", &b=" << &b << ", &c=" << &c << endl;

	c = 100;
	cout << "赋值后,a=" << a << ", b=" << b << ", c=" << c << endl;
	cout << "赋值后,&a=" << &a << ", &b=" << &b << ", &c=" << &c << endl;
}

常量引用

const int &ref = x; 常用于方法入参
不能通过常量引用修改值
可以直接修改原始变量值

int a = 10;
const int& ref = a;

cout << "修改前,a=" << a << " ,ref=" << ref << endl;

// 不能通过 const 引用修改值
//ref = 20;  

// 可以,但 ref 的值也变为 100
a = 100;
cout << "修改后,a=" << a << " ,ref=" << ref << endl;

使用引用场景

  1. 函数入参传递(尤其是大对象)
  2. 函数出参需要修改
  3. 避免拷贝、提高性能
void print(const string &str); 

使用指针场景

  1. 可能为空的情况
  2. 动态内存管理
  3. 需要重新指向不同对象
  4. 实现数据结构(链表、树、图等)
  5. 与 C语言交互(C 语言没有引用)

智能指针

智能指针 头文件 所有权模型 用途
std::unique_ptr <memory> 独占所有权 单个所有者
std::shared_ptr <memory> 共享所有权 多个所有者
std::weak_ptr <memory> 非拥有引用 解决循环引用

std::unique_ptr

  1. 独占所有权:同一时间只能有一个 unique_ptr 指向对象
  2. 不可复制:但可以移动(Move)
  3. 自动释放:析构时自动调用 delete
//std::unique_ptr<int[]> p = std::make_unique<int[]>(10);
std::unique_ptr<int> p = std::make_unique<int>(10);
cout << "修改前,p=" << p << " ,*p=" << *p << endl;

*p = 100;
cout << "修改后,p=" << p << " ,*p=" << *p << endl;

// 不能复制
// auto p1 = p;

// 移动后,p变成空指针
auto p1 = std::move(p);
cout << "移动后,p1 = " << p1 << ", *p1 = " << *p1 << endl;
cout << "移动后,p = " << p << ", *p = " << *p << endl;

std::shared_ptr

  1. 共享所有权:多个 shared_ptr 可以指向同一对象
  2. 引用计数:内部维护引用计数,计数为0时自动释放
  3. 可以复制
std::shared_ptr <int> p1 = std::make_shared<int>(10);
cout << "p1:" << p1.use_count() << endl;

{
	// 复制,共享所有权
	std::shared_ptr <int> p2 = p1;
	cout << "p1:" << p1.use_count() << endl;
	cout << "p2:" << p2.use_count() << endl;
	// 作用域结束,自动释放
}
cout << "p1:" << p1.use_count() << endl;

std::weak_ptr

解决 shared_ptr 的循环引用问题

  1. 不增加引用计数
  2. 不拥有对象
  3. 必须通过 lock() 转换为 shared_ptr 才能访问对象
std::shared_ptr<int> p = std::make_shared<int>(10);
std::weak_ptr<int> wptr = p;

// 检查对象是否还存在
if (auto locked = wptr.lock()) {
	cout << *locked << endl;  
}
else {
	cout << "对象已释放" << endl;
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐