2025-02-09 ·
日常编程 ·
182620
对于C/C++编程初学者来说,指针是最难理解的概念之一。许多学生为此苦恼,许多开发者都尽量避免使用指针。然而,理解指针至关重要,因此,让我们从基础开始。
什么是指针?
指针是一种数据类型,类似于int、float等。声明指针的语法是在类型名后添加*。例如,指向整数的指针声明为int *,指向自定义结构mytype的指针声明为mytype *。
指针指向的是变量的内存地址。int *存储整数变量的地址,mytype *存储mytype变量的地址。
示例:
#include <iostream>
int main(){
int value = 42;
int* p = &value; // p指向value的内存地址
std::cout << "Value: " << value << ", Address: " << &value << ", p: " << p << std::endl;
}
代码示例1
主要指针操作符
除了存储变量的地址外,指针还有两个主要操作:解引用和指针算术。
解引用
使用*操作符解引用指针,访问指针指向的内存单元中的值。
#include <iostream>
int main(){
int var = 42;
int *p = &var; // p指向var的内存地址
*p = 21; // 修改var的值为21
}
代码示例2
未初始化的指针非常危险,因为它可能指向内存中的任意位置,导致程序崩溃或出现未定义行为。
指针算术
指针算术允许修改指针的值(即内存地址)。指针可以进行加减运算,也可以与整数进行加减运算。需要注意的是,指针加减运算的步长是所指向数据类型的字节大小。例如,如果p是指向整数的指针,p++会使p指向下一个整数的地址。
指针算术需要谨慎使用,因为它允许直接操作内存。
#include <iostream>
int main(){
int v = 21;
int w = 42;
int *p = &w; // p指向w
p++; // p指向v
*p += 1; // v的值加1
std::cout << "v: " << v << std::endl;
}
代码示例3
如示例所示,我们可以通过指针算术修改未直接赋值的变量的值。
空指针
类似于数字0在数字中的特殊地位,空指针(nullptr)在指针中也扮演着重要的角色。空指针表示指针不指向任何有效的内存地址。 在使用指针之前,务必检查其是否为空,避免程序崩溃或出现错误。
#include <iostream>
int* foo(int value){
static int answ = 42;
if(answ == value){
return &answ;
} else {
return nullptr;
}
}
int main(){
int *p = foo(21);
if (p != nullptr) {
// 使用p
}
}
代码示例4
关键点
总结一下,我们学习了:
指针是存储内存地址的变量。
始终初始化指针,未初始化的指针可能导致程序崩溃。
在解引用指针之前,始终检查其是否为空。
谨慎使用指针算术。
希望这篇指南能帮助你更好地理解C/C++中的指针。 继续学习,探索更多!
以上就是指针,一个怪异的野兽,适合初学者及以后的详细内容,更多请关注骃骐网【www.myinqi.com】。
快慢指针能检测环是因为有环时相对速度为1,有限步内必相遇;无环时快指针先达None。需检查空链表、单节点、自环等边界条件,循环条件应为while fast and fast.next,用is比较节点,相遇后可求环入口。 快慢指针为什么能检测环 核心在于:如果链表有环,快指针(每次走2步)迟早会追上慢指针(每次走1步);如果无环,快指针必然先走到 None。这不是概率问题,而是数学上的相遇必然性——...
2026-05-29 · 日常编程 · 87968
倒序读取大文件应使用seek()和readline()控制文件指针,而非readlines()[::-1]以免OOM;需以'rb'模式打开,从末尾逐字节回退识别换行符,兼容\r\n,用生成器实现内存友好。 用 seek() 和 readline() 从文件末尾倒着读行 直接 readlines()[::-1] 会把整个文件加载进内存,大文件(比如几百 MB 的日志)容易 OOM。真正可行的倒序读取...
2026-05-27 · 日常编程 · 104888
C++23通过std::expected、std::propagate_const等新特性增强智能指针生态,提升资源管理的安全性与代码清晰度,同时引入std::print、if consteval和Lambda显式模板参数,改进错误处理、输出和编译期编程,推动现代C++向更安全高效的开发模式演进。 C++ 的智能指针和新特性一直在演进,目标是让资源管理更安全、更高效,代码更清晰。C++23 带来了...
2025-08-28 · 日常编程 · 101111
智能指针的控制块是实现共享所有权和自动资源管理的核心机制,尤其在 std::shared_ptr 中起着关键作用。理解其内部结构有助于掌握其性能特征和使用注意事项。 控制块的基本组成 控制块是一个动态分配的结构体,由 std::shared_ptr 在首次创建时生成,用于管理所指向对象的生命周期。它通常包含以下成员: 引用计数(shared reference count):记录当前有多少个 sh...
2025-08-28 · 日常编程 · 310614
智能指针通过RAII机制实现内存自动管理,利用对象生命周期控制资源;std::unique_ptr独占所有权,std::shared_ptr引用计数共享资源,std::weak_ptr打破循环引用,三者均在析构时释放内存,避免泄漏。 智能指针的核心在于自动管理动态分配的内存,避免内存泄漏和悬空指针。这背后的关键机制是RAII(Resource Acquisition Is Initializati...
2025-08-28 · 日常编程 · 25095
本文深入探讨了Go语言中空指针解引用(nil pointer dereference)错误的常见原因及其预防策略。通过分析Go的零值概念,并结合具体代码示例,详细阐述了如何通过选择合适的类型(如[]*struct)、显式初始化、以及必要的nil检查等方法,有效地构建健壮且避免运行时panic的Go应用程序。理解Go语言中的空指针解引用 在go语言中,空指针解引用(nil pointer deref...
2025-08-27 · 日常编程 · 112994
本文深入探讨 Go 语言中常见的空指针解引用(nil pointer dereference)错误,特别是涉及结构体字段和切片指针的场景。通过分析问题代码,提供了一种更符合 Go 语言习惯的解决方案,即使用 []*struct 代替 *[]struct,并强调了 Go 语言零值初始化、显式初始化以及必要时进行 nil 检查等关键实践,旨在帮助开发者编写更健壮、更可靠的代码。在 Go 语言中,空指针...
2025-08-27 · 日常编程 · 160404
zuojiankuohaophpc++np>数组作为函数参数时会退化为指针,因为c++不会完整传递整个数组,而是传递指向首元素的指针。1. 退化本质:数组参数自动转换为指针,如void func(int arr[]);等价于void func(int arr);。2. 信息丢失问题:在函数内使用sizeof(arr)得到的是指针大小而非数组实际大小。3. 解决方法包括:手动传递长度void ...
2025-08-25 · 日常编程 · 18250
别名构造通过共享控制块但指向不同对象,实现精细资源管理,如Container中返回data成员的shared_ptr,延长宿主生命周期,需确保成员不先于宿主销毁,且宿主由shared_ptr管理。 智能指针的“别名构造”是一种高级用法,主要用于共享同一个控制块(control block)的所有权,但指向不同的对象地址。这在某些特定场景下非常有用,比如封装代理对象、实现引用封装或自定义资源管理时。...
要有效避免c++++内存泄漏,应使用智能指针与raii技术。1. 使用std::unique_ptr、std::shared_ptr和std::weak_ptr自动管理内存,确保资源在生命周期结束时释放;2. 通过raii技术将资源获取与释放绑定到对象构造与析构,防止异常导致的资源未释放;3. 注意避免shared_ptr循环引用问题,合理使用weak_ptr打破循环;4. 尽量避免裸指针,必须使...
2025-08-25 · 日常编程 · 214521