一些小知识点

左/右移的本质

无论是左移还是右移,a << b 中的数值主体总是 \(a\),如果 a 不是 long long 类型,即使 b 的 long long,该爆的时候还是会爆

unordered_map 的 hash

unordered_map 只对基本的几种类型有 hash 方式,如 int,long long,bool,string,char 等等基本类型有 hash。而对于 vector,pair,int128,unordered_map 等其他库类型没有 hash。

unique 和 remove 的原理

节选自 AI,可以看出,这个相当于覆盖,而非把数据放到队尾。

主要工作流程

假设一个序列 [1, 2, 3, 2, 4],要删除所有值为 2 的元素:

  1. 使用两个迭代器:一个“读指针”遍历原始序列,一个“写指针”标记下一个可写入位置。

  2. 遍历:对于每个元素:

    • 如果该元素不等于要删除的值,就把它复制/移动到写指针当前位置,然后写指针前进;

    • 如果等于要删除的值,则只移动读指针,写指针不动。

  3. 最终:写指针指向的位置就是所有“保留元素”的下一个位置,它作为新的逻辑尾部返回。

经过 std::remove 后,容器中的元素排列变为:
[1, 3, 4, 2, 4]
─ 前 3 个元素是保留的 1, 3, 4
─ 后面的 2, 4 是原本在后面的元素(属于“残留”状态,内容未定义但可被覆盖)

左值和右值

  • 左值:表示一个有明确身份、可以反复找到的对象。
  • 右值:通常表示临时值,使用完就可以被销毁或移动。
    不具体的说,左值是存在名字的量,而右值是临时值会随时销毁。

左值引用

int &a = b; 首先这类的引用都是一个道理——必须在声明时赋值,因为是引用本身用起来是别名的效果,为了简化代码书写使用。

需要注意一些小问题,在 int &a = b; 里面 & 是每个变量单独的声明符号,所以有 int &a, &b; 这种情况,有的时候会见到 int& a; 这种写法,这种写法等价与 int &a;,但是 int& a, b; 等价与 int &a, b; 而非 int &a, &b;int& a; 只是一种写法而已, & 是每个变量单独否符号。

同时一维数组的话是 int (&tx)[] = g; 这样引用,或者简单点 auto &tx = g[x];

对于二维数组的话也是 int (&tx)[N][M] = g; 这里必须数组大小和 \(g\) 一样。引用必须知道是什么类型的。

不过还是推荐直接 auto &tx = g; 就行了。

C++ 的复杂类型

一般情况下各种类型都能通过 auto 直接简化声明。

对于数组来说,数组大小也是类型的一部分,因此可以引申出来一堆类型,有很多复杂的类型我们根本没法写出来,只能用 auto。有时候也就是挺恶心的。

字面量的地址

同一个字符串字面量对象在一次程序运行期间地址不会改变。因为作为数组他有静态存储期,从程序开始到结束。但是 C++ 标准不保证这玩意,所以不一定是完全相同。

而普通的字面量就是纯右值,用完就释放,无法引用地址。而字符串字面量是左值。

posted @ 2026-08-05 11:33  blind5883  阅读(6)  评论(0)    收藏  举报