C++语言特性相关

1.左值引用右值引用

左值(Lvalue,Locator Value)指的是可以被取地址的值,即在表达式结束后仍然存在的对象。例如,变量、数组元素、对象等都是左值。

左值引用用于绑定左值,并且通常用于传递和修改可变对象。

1
2
3
int a = 10;
int& ref = a; // ref 绑定到 a
ref = 20; // 修改 ref 也会影响 a

右值(Rvalue,Right-hand value)指的是无法取地址的临时值,通常是表达式计算的结果,如字面量、临时变量等。

右值引用使用 && 语法,用于绑定右值,使得右值可以被高效地移动,而不是复制。

1
2
int&& rref = 10;  // 10 是右值,可以绑定到右值引用
std::cout << rref << std::endl; // 输出 10

左值引用 vs 右值引用

左值引用 & 右值引用 &&
绑定对象 只能绑定左值 只能绑定右值
修改对象 可以修改 可以修改
适用场景 传递可变对象 移动语义、避免拷贝
常见用法 普通变量引用、函数参数 移动构造、移动赋值

2.左值引用和右值引用的转化

  • std::move():是一个转换工具,用于将左值强制转换为右值,从而触发移动语义
  • std::forward<T>():主要用于泛型编程,保证在模板参数传递时,保留左右值的原始属性,实现完美转发
  • std::move_if_noexcept():在某些情况下,如果移动构造可能抛出异常,我们可能更希望使用拷贝构造std::move_if_noexcept 可用于这种情况

3.指针的大小与用法

  • 指针的大小和编译器的目标平台的位数,而与所指向的数据类型无关。如果是32位的机器,则指针的大小则是4Byte,如果是64位机器,那么指针的大小是8Byte。
  • 指针存储变量的内存地址,使用 & 获取地址,使用 * 解引用指针以访问数据。
  • 指针作为函数参数:实现传址调用,允许函数直接修改原始数据。函数指针:用于回调机制或策略模式等

4.指针和引用的区别

总结对比表

特性 指针 引用
是否需要初始化 不需要,可以为空 必须初始化
是否能重新指向 可以 不可以
是否可为空 可以指向 nullptr 不可以
是否有独立内存 是,占用内存存储地址 否,与原变量共用内存
是否可修改值 通过 * 解引用后可修改 可修改(除非 const 修饰)
典型应用场景 动态内存分配、数据结构 参数传递、引用更安全的别名

5.指针常量和常量指针

常量指针(const T*:指向的值不能修改,但指针本身的指向可以更改。(即只能读,不能修改)

指针常量(T* const:指针本身的指向不能更改,但指向的值可以修改

6.函数指针的定义

函数指针 (Function Pointer) 是指向函数的地址的指针。与普通指针不同,函数指针指向的是可执行代码段中的函数入口地址,而非数据

函数指针的基本语法

定义函数指针的一般形式为:

1
返回类型 (*指针变量名)(参数类型列表);

7.CPP中函数传递参数的方法

在 C++ 中,函数传递参数的方式主要有以下几种:

  1. 值传递(Pass by Value)

    • 形参是实参的副本,在函数内对参数的修改不会影响原始数据。
    • 适用于基本数据类型,但对于大对象会导致不必要的拷贝开销。
    1
    void func(int x) { x = 10; }
  2. 引用传递(Pass by Reference)

    • 形参是实参的引用,函数内的修改会直接影响原始数据。
    • 适用于需要修改参数的情况,或者避免拷贝大对象以提升效率。
    1
    void func(int& x) { x = 10; }
  3. 指针传递(Pass by Pointer)

    • 形参是指向实参的指针,可以在函数内修改原数据。
    • 需要检查指针是否为空,避免空指针访问错误。
    1
    void func(int* x) { if (x) *x = 10; }
  4. 常量引用传递(Pass by Const Reference)

    • 适用于大对象的只读传递,既避免了拷贝,又保证了数据不会被修改。
    1
    void func(const std::string& str) { std::cout << str; }
  5. 右值引用传递(Pass by Rvalue Reference)(C++11及以上)

    • 允许传递右值(临时对象),通常用于移动语义(move semantics),提高效率。
    1
    void func(std::string&& str) { std::cout << str; }
  6. 智能指针传递(Pass by Smart Pointer)(C++11及以上)

    • 通过 std::shared_ptrstd::unique_ptr 传递对象,管理内存生命周期。
    1
    void func(std::shared_ptr<int> ptr) { std::cout << *ptr; }

不同的方式适用于不同的场景,应根据性能需求数据安全性来选择合适的参数传递方式。

8.迭代器

迭代器(Iterator)是 C++ STL(标准模板库) 中用于遍历容器(如 vectorlistmap 等)的一种通用接口。迭代器提供了一种类似指针的方式来访问容器中的元素,同时又能适应不同类型的容器。

C++ 提供了 五种迭代器,分别适用于不同类型的容器和操作:

迭代器类型 说明 适用容器
输入迭代器 (InputIterator) 只能 从前向后读取 数据 istream_iterator
输出迭代器 (OutputIterator) 只能 向前写入 数据 ostream_iterator
前向迭代器 (ForwardIterator) 可读可写,可单向移动 forward_list
双向迭代器 (BidirectionalIterator) 可读可写,可双向移动 listmapset
随机访问迭代器 (RandomAccessIterator) 可读可写,可随机跳转 vectordeque

常见 STL 容器的迭代器

容器 begin() end() 迭代器类型
vector vector<int>::iterator vector<int>::iterator 随机访问
list list<int>::iterator list<int>::iterator 双向
map map<int, int>::iterator map<int, int>::iterator 双向
set set<int>::iterator set<int>::iterator 双向

9.野指针和悬空指针

野指针 vs 悬空指针

类别 定义 产生原因 如何修正
野指针 未初始化的指针,指向未知地址 1. 没有初始化 2. 释放后未置空 3. 超出作用域 初始化指针为 nullptr
悬空指针 指向已释放的无效内存 1. 释放后仍然访问 2. 作用域结束后访问 3. 二次释放 释放后将指针置空

10.类型转化

static_cast vs dynamic_cast

特性 static_cast dynamic_cast
转换时间 编译时 运行时
是否安全检查 ❌ 无检查 ✅ 运行时检查
适用范围 基本类型、多态类型、void* 仅适用于多态类型
转换失败时 未定义行为 返回 nullptr(指针)/ 抛异常(引用)
速度 ⚡ 高效 🐢 慢(因运行时检查)

四种转换方式对比

转换类型 转换方式 运行时检查 适用范围 推荐使用情况
static_cast 编译时转换 ❌ 无 兼容类型转换 ✅ 用于安全转换,如 int → double
dynamic_cast 运行时转换 ✅ 有 多态类型(有虚函数) ✅ 适用于父子类转换,确保安全
const_cast 移除/添加 const ❌ 无 指针/引用 ✅ 需要修改 const 变量时
reinterpret_cast 低级转换 ❌ 无 指针/整数/位级转换 ⚠️ 极少使用,仅用于底层编程
作者

kosa-as

发布于

2025-02-25

更新于

2025-03-18

许可协议

评论