C++ STL之vector详解:从使用到底层,再到面试八股

华为OD C++面试STL核心考点:容器原理、性能优化与实战指南 在C++编程中,标准模板库(STL)是实现高效、可复用代码的核心工具。其设计基于泛型编程思想,通过容器、算法、迭代器等组件的解耦,提供了强大的数据结构和算法支持。理解STL的底层原理,如vector的动态扩容机制和map的红黑树实现,有助于开发者掌握内存管理与性能优化的关键。在工程实践中,合理选择容器(如vector、list、map)和算法,能显著提升程序效率,避免迭代器失效等常见陷阱。对于准备华为OD等研发岗位面试的候选人,深入掌握STL不仅是应对面试八股文的基础,更是提升C++编程能力、编写健壮高性能 阅读详情

C++ STL之vector详解:从使用到底层,再到面试八股

本文面向面试和日常开发,先讲调用,再讲原理,最后给口语化面试答案。


一、用法速查

1.1 初始化

#include <vector>
#include <iostream>
using namespace std;

int main() {
    // 一维初始化
    vector<int> v1;                    // 空数组
    vector<int> v2(5);                 // 5个元素,默认0
    vector<int> v3(5, 1);              // 5个1
    vector<int> v4{1, 2, 3, 4, 5};     // 初始化列表
    vector<int> v5(v4);                // 拷贝构造
    vector<int> v6 = v4;               // 拷贝赋值

    // 二维初始化
    vector<vector<int>> v2d1;                        // 行列均可变
    vector<vector<int>> v2d2(3, vector<int>(4, 0));  // 3行4列,值0
    vector<int> row[5];                              // 行固定5,列可变

    // C++17 CTAD(类模板参数推导)
    vector v7{1, 2, 3};                // 推导为 vector<int>
    vector v8(5, "hello");             // 推导为 vector<string>

    for (int x : v4) cout << x << " "; // 1 2 3 4 5
}

1.2 元素访问

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> v{10, 20, 30, 40, 50};

    cout << v[0] << "\n";              // 10,不检查越界
    cout << v.at(1) << "\n";           // 20,越界抛 out_of_range
    cout << v.front() << "\n";         // 10
    cout << v.back() << "\n";          // 50

    int* p = v.data();
    cout << p[2] << "\n";              // 30,data()返回底层数组指针
}

1.3 大小操作

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> v;
    cout << v.size() << "\n";          // 0
    cout << v.empty() << "\n";         // 1 (true)

    v.resize(5, 1);                    // size=5, 填充1
    cout << v.size() << "\n";          // 5
    cout << v.capacity() << "\n";      // >=5

    v.reserve(100);                    // 预分配capacity=100
    cout << v.capacity() << "\n";      // 100

    v.push_back(2);
    cout << v.size() << "\n";          // 6,原有5个1 + 尾部2

    v.shrink_to_fit();                 // 请求减小capacity到size
    cout << v.capacity() << "\n";      // >=6(非强制,具体看实现)
}

1.4 增删元素

#include <vector>
#include <iostream>
using namespace std;

void print(const vector<int>& v) {
    for (int x : v) cout << x << " ";
    cout << "\n";
}

int main() {
    vector<int> v;

    v.push_back(1);                    // 尾部插入1
    v.push_back(2);                    // 尾部插入2
    v.emplace_back(3);                 // 原地构造,尾部插入3
    print(v);                          // 1 2 3

    v.pop_back();                      // 删除尾部元素
    print(v);                          // 1 2

    v.insert(v.begin() + 1, 99);       // 在位置1插入99
    print(v);                          // 1 99 2

    v.erase(v.begin() + 1);            // 删除位置1的元素
    print(v);                          // 1 2

    v.clear();                         // 清空所有元素
    cout << v.size() << "\n";          // 0
    cout << v.capacity() << "\n";      // 不变
}

1.5 遍历

#include <vector>
#include <iostream>
#include <ranges>
using namespace std;

int main() {
    vector<int> v{10, 20, 30, 40, 50};

    // 迭代器
    for (auto it = v.begin(); it != v.end(); ++it)
        cout << *it << " ";            // 10 20 30 40 50
    cout << "\n";

    // 范围for(只读)
    for (int x : v) cout << x << " ";
    cout << "\n";

    // 范围for(可写)
    for (int& x : v) x *= 2;

    // C++20 std::ranges
    for (int x : v | views::take(3))
        cout << x << " ";              // 20 40 60
    cout << "\n";

    // 反向迭代器
    for (auto it = v.rbegin(); it != v.rend(); ++it)
        cout << *it << " ";            // 100 80 60 40 20
    cout << "\n";
}

二、底层原理

2.1 动态数组与连续内存

vector 的底层是一块连续堆内存,内部维护三个指针:

┌────────────┬────────────┬────────────┐
│   _start   │   _finish   │  _end_of_storage  │
│ (数据首地址) │ (数据尾地址)  │ (容量尾地址)      │
└────────────┴────────────┴────────────┘
  • _start:指向堆上分配的内存块起始
  • _finish:指向当前最后一个元素的下一个位置(即 size())
  • _end_of_storage:指向已分配内存的末尾(即 capacity())

所以 size() = _finish - _start,capacity() = _end_of_storage - _start。

与 array 和 list 的内存模型对比:

容器内存布局分配位置随机访问
array栈上连续栈O(1)
vector堆上连续堆O(1)
list节点离散,指针连接堆O(N)

连续的堆内存意味着 vector 在随机访问、缓存局部性(cache locality)上有绝对优势——遍历 vector 的顺序元素时 CPU 预取器能高效工作,而 list 的节点分散在各处,每次访问都可能 cache miss。

2.2 扩容机制与均摊分析

当 _finish 追上 _end_of_storage 时,vector 必须扩容。标准流程:

  1. 分配一块更大的新内存(典型为当前 capacity 的 1.5~2 倍)
  2. 将旧元素移动或拷贝到新内存
  3. 销毁旧元素,释放旧内存
  4. 更新三个指针指向新内存
// 伪代码示意
void push_back(const T& val) {
    if (_finish == _end_of_storage) {
        size_t new_cap = _capacity * growth_factor;  // 2x or 1.5x
        T* new_buf = new T[new_cap];
        for (size_t i = 0; i < size(); ++i)
            new_buf[i] = std::move_if_noexcept(_start[i]);
        delete[] _start;
        _start = new_buf;
        _finish = _start + old_size;
        _end_of_storage = _start + new_cap;
    }
    *_finish = val;
    ++_finish;
}

GCC 2x vs MSVC 1.5x 策略差异:

编译器扩容倍数分配器特点
GCC/libstdc++2xrealloc 语义不可用,纯 malloc+copy+free
Clang/libc++2x同上
MSVC1.5x碎片友好,旧块可被回收复用

为什么 GCC 用 2x,MSVC 用 1.5x? 2x 均摊分析最简单,GCC 选择 2x 是历史惯性。MSVC 在调研后选择了 1.5x,因为实验表明 1.5x 在 Windows 堆分配器(segment heap)上能显著减少外部碎片——旧释放块的尺寸总和能更快追上新分配块,使这些旧块可以被后续分配复用。

碎片成因分析:

2x 扩容(MSVC):  释放16 → 分配32(旧16无法复用)
                  释放16+32 → 分配64(旧48 < 64,无法复用)
                  释放16+32+64 → 分配128(旧112 < 128,无法复用)

1.5x扩容(MSVC): 释放16 → 分配24
                  释放16+24 → 分配36(旧40 > 36,可复用)

均摊 O(1) 证明:

设初始容量为 1,扩容倍数为 k(k > 1)。扩容到容量 N 时的总拷贝次数:

T(N) = 1 + k + k² + ... + k^(log_k(N)-1)
     = (k^(log_k(N)) - 1) / (k - 1)
     = (N - 1) / (k - 1)
     = O(N)

N 次 push_back 总拷贝 O(N),均摊每次 O(1)。这就是为什么 push_back 虽然偶尔 O(N) 扩容,但整体是 O(1)。

2.3 emplace_back vs push_back

两者最核心的区别:push_back 接收一个已构造好的对象,emplace_back 接收构造参数,在容器内部原地构造。

struct Person {
    string name;
    int age;
    Person(string n, int a) : name(move(n)), age(a) {}
};

int main() {
    vector<Person> v;

    // push_back: 先构造临时 Person,再移动/拷贝到容器
    v.push_back(Person("Alice", 25));
    // 等价于 → 临时对象构造 → 移动构造到vector → 析构临时对象

    // emplace_back: 直接传入参数,在vector的内存中原地构造
    v.emplace_back("Alice", 25);
    // 等价于 → 在vector的已有空间上直接调用 Person("Alice",25)
}

emplace_back 省掉了临时对象的构造和析构,对 Person("Alice", 25) 这种非平凡类型有明显性能优势。对于 int、double 等基本类型,两者几乎没有区别。

完美转发(Perfect Forwarding): emplace_back 是可变参数模板,通过 std::forward 将参数完美转发到构造函数:

template <typename... Args>
reference emplace_back(Args&&... args) {
    if (_finish == _end_of_storage) grow();
    ::new (_finish) T(std::forward<Args>(args)...);
    ++_finish;
    return back();
}

注意它使用了 placement new,直接在已分配但未构造的内存上构造对象,不涉及任何临时对象。

2.4 迭代器失效完整场景表

迭代器失效是 vector 面试的核心考点。失效的本质是:vector 重新分配了底层内存,原有指针全部指向已释放的旧内存。

操作条件哪些迭代器/引用/指针失效
push_back / emplace_back触发了扩容全部失效
push_back / emplace_back未触发扩容仅 end() 迭代器失效
pop_back—仅被删除元素的迭代器及 end()
insert触发了扩容全部失效
insert未触发扩容插入位置及之后的所有迭代器失效
erase(单个元素)—被删元素及之后的所有迭代器失效
erase(区间)—被删区间及之后的所有迭代器失效
reserve新容量 > 旧容量全部失效
reserve新容量 <= 旧容量无失效
shrink_to_fit触发了重分配全部失效
resize新 size > 旧 capacity全部失效
clear—全部失效(但可以直接用 v.begin() 重新获取)

理解规律:任何可能导致底层内存重分配的操作,全部失效;任何导致元素位置移动的操作(插入/删除中间的某个元素,后续元素向前/后挪),从变动位置开始往后的迭代器全部失效。

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> v{1, 2, 3, 4, 5};
    auto it = v.begin() + 2;           // 指向3

    v.insert(v.begin() + 1, 99);       // 未触发扩容
    // 此时 v = {1, 99, 2, 3, 4, 5}
    // it 原指向3,但插入后3的位置变到了 v.begin() + 3
    cout << *it << "\n";               // 未定义行为!it已失效
}

正确做法:插入/删除后重新获取迭代器:

auto it = v.begin() + 2;
it = v.insert(it, 99);                 // insert返回新插入元素的迭代器
// it 此时指向99,安全

2.5 扩容过程图解(Mermaid)

否

是

push_back()调用

_finish == _end_of_storage?

在_finish位置构造元素

分配新内存
new_cap = cap x factor

将旧元素 move 到新内存

销毁旧元素
释放旧内存

更新迭代器

_finish 自增

push_back 完成


三、面试题 + 口语化答案

Q1:vector 的扩容倍数为什么 GCC 是 2 倍、MSVC 是 1.5 倍?

“2 倍是典型的空间换时间——拷贝次数少,均摊 O(1) 的常数更小。但 2 倍在 MSVC 上会产生严重的内存碎片,因为每次新分配都比所有旧块总和还大,旧的永远没法复用。MSVC 用 1.5 倍就是为了让旧释放块的尺寸能更快追上新分配尺寸,减少外部碎片。GCC 选 2 倍主要是历史原因——libstdc++ 没有 realloc 优化,2 倍的均摊分析更简单。面试官如果问你这个,你从’均摊 O(1) 的常数因子’和’碎片复用’两个角度答就稳了。”

Q2:resize 和 reserve 有什么区别?

“resize(n) 改变的是 size——数组中实际元素的个数。如果 n > size 会在末尾补默认值,如果 n < size 会截断。reserve(n) 改变的是 capacity——预分配内存空间,不改变元素个数,也不构造任何对象。一句话:resize 管能看到多少元素,reserve 管不扩容能塞多少元素。面试常见的坑是有人用 reserve(100) 之后直接 v[i] = x 访问——这是未定义行为,reserve 只分配内存没构造对象。”

Q3:emplace_back 比 push_back 快在哪?

“push_back 是先在外面构造一个临时对象,然后移动或拷贝到容器里,再析构临时对象。emplace_back 是直接在容器的内存上原地构造——传入构造参数,用完美转发调用构造函数。省了一个临时对象的构造和析构。对于 int 这种基本类型区别不大,但对于 string、pair、自定义结构体这种有非平凡构造函数的类型,emplace_back 有明显优势。面试答到这个程度就够了,如果再深问,可以说’本质是 placement new 加完美转发’。”

Q4:vector 有什么坑?

“vector<bool> 不是普通的 vector——标准库对其做了特化,把每个 bool 压缩到一个 bit 里。这导致 operator[] 返回的不是 bool&,而是一个代理对象 reference。你不能拿它的地址,不能做 auto& ref = v[0]。而且 vector<bool> 的迭代器也不符合标准容器的要求。如果不做这种压缩,可以用 deque<bool> 或自己包装 vector<char> 来替代。面试官问这个一般是考察你是否知道 STL 里有这种特化陷阱。”

Q5:vector 的迭代器什么时候会失效?

“分三种情况。第一,任何导致内存重分配的操作——push_back 触发扩容、reserve 新容量大于旧容量——所有迭代器、引用、指针全部失效。第二,插入或删除中间元素——即使不触发扩容,插入/删除位置之后的所有迭代器也会失效,因为元素往后或往前挪了。第三,erase 之后用原迭代器——被删除元素及之后的所有迭代器都失效了。记忆规律就是:vector 的迭代器极容易失效,只要你触发了内存搬迁或元素挪动,就全废了。”

Q6:shrink_to_fit 的原理是什么?

“shrink_to_fit 做的事情是:分配一块正好容纳当前 size 的新内存,把元素搬过去,释放旧内存。它不是强制性的——标准说这是’请求’,不是’命令’,实现可以忽略它。底层就是做一次 vector<int>(*this).swap(*this),也就是用当前内容拷贝构造一个临时 vector(容量刚好等于 size),再和当前 vector 交换数据。C++11 引入这个函数就是为了解决’清空元素后 capacity 仍然很大的问题’。”

Q7:clear 之后 capacity 变不变?

“不变。clear 只把 _finish 指针移回 _start 位置,销毁所有元素,但不释放底层内存块。capacity() 返回值不变。如果你要释放内存,需要用 vector<int>().swap(v) 或 v.shrink_to_fit()(非强制)。这也是为什么连续 clear + push_back 不会触发重复分配——capacity 还在。”

Q8:vector 的移动构造为什么是 O(1)?

“vector 的移动构造只是把源对象的三个指针(_start、_finish、_end_of_storage)复制过来,然后把源指针置空。不涉及任何元素级别的拷贝,和元素个数完全无关。三个指针的赋值就是 O(1)。移动赋值也一样——交换三个指针就完了。这是 vector 一个重要的性能优势:拷贝一个 100 万个元素的 vector 是 O(N),移动是 O(1)。”

Q9:vector 和 list 在什么场景下互有优势?

“vector 连续内存,随机访问 O(1),缓存友好,插入只在尾部高效;list 节点离散,随机访问 O(N),但任意位置插入删除都是 O(1)(前提是你已经有迭代器了)。高频随机访问、尾部插入频繁选 vector;头部或中间频繁插入删除、且对顺序访问不敏感选 list。还有一个维度:vector 的迭代器很容易失效,list 的迭代器除了被删除的那个,其他全部有效。”

Q10:怎么让 vector 提前释放多余的内存?

“C++11 之前用 vector<int>(v).swap(v)——用 v 的内容构造一个临时 vector(capacity 刚好等于 size),交换 v 和临时对象的内部指针,临时对象析构时释放旧内存。C++11 起直接用 v.shrink_to_fit()。需要注意 shrink_to_fit 是 non-binding 的,实现可以不执行。VC 的 debug 模式下可能忽略,GCC 基本都会执行。”


一句话总结:vector 的核心价值在于连续内存的缓存友好和随机访问 O(1),代价是扩容时迭代器大面积失效和中间插入的低效——理解扩容策略、失效场景和 emplace_back 的性能优势,就是掌握了 vector 的全部面试考点。

C++后端高频八股深度拆解:从智能指针到内存序 C++语言以高效灵活著称,但也对开发者的底层功底提出极高要求。智能指针作为资源管理的核心工具,其引用计数机制解决了手动内存释放的痛点,而weak_ptr则进一步化解循环引用难题。虚函数与多态的实现依赖虚函数表,理解对象模型有助于写出高性能代码。在并发编程中,原子变量与内存序决定了多线程同步的正确性与性能边界,是后端服务稳定性的基石。这些知识点不仅出现在大厂面试中,更直接影响工程实践中的系统设计。基于牛客面经与真实面试经验,深入拆解高频八股考点及其考察逻辑,帮助读者构建从原理到应用的知识框架,举一反三应对C+ 阅读详情

相关推荐

C++ 面试八股文总结 -- STL

C++ 面试八股文总结 -- STL

m0_47999117的博客 8371

C++ STL面试八股:从vector扩容到红黑树,底层原理全拆解

C++开发岗位面试中,STL几乎是必考环节。不少候选人能熟练调用容器和算法,却在“vector为什么按1.5倍或2倍扩容”“map为何选用红黑树而非AVL树”“迭代器何时失效”这类底层追问前卡壳。从数据结构选型到内存管理,从移动语义到异常安全,STL的设计处处体现着性能与工程可维护性的权衡。理解这些原理不仅能帮助通过技术面试,更能指导日常开发中容器与算法的合理选用。本文基于高频面试考点,拆解vector扩容机制、红黑树与哈希表的取舍、迭代器失效规则、sort的内省排序实现,以及C++11以后移动语义带来的性

weixin_33404102的博客 229

C++面试八股-STL(vector)

vector的容量是可以动态改变的,一般情况下使用vector的步骤是:声明一个vector并指定其元素的数据类型---初始化该vector的容量大小---往该vector增删改查元素---销毁或回收vector内存。vector的扩容操作步骤如下:达到扩容阈值---新开辟一块大小是原vector容量的若干倍的连续内存控件---将原vector的所有数据拷贝至新开辟的内存---让vector指向新的内存---回收原先vector开辟的内存---插入新的元素。个数,并非获取vector实际开辟的内存大小。

int_p的博客 1960

C++数据结构学习路线:从入门到面试八股与实战

数据结构是计算机程序的骨架,C++通过指针、内存管理和模板机制将其落地为高效代码。理解数组、链表、栈、队列、树、哈希表等核心结构的底层原理,才能看懂vector扩容为何均摊O(1)、map为何基于红黑树,以及冒泡排序算法C++实现中的边界优化。这些原理既是面试八股文的考察重点,也是工程实践中做性能优化和架构设计的根基。从VS Code配置C/C++环境起步,到堆栈内存模型、排序算法对比,再到植物百科数据管理这类课程设计与贪吃蛇等c++小游戏实战,一条主线贯穿知识、考试与真实场景。本文梳理C++数据结构的系统

weixin_28339967的博客 142

C++面试八股文:std::vector和std::list,如何选择?

它的底层是单向链表,引入它的主要目的是为了达到手写链表的性能。指针指向的对象,而不需要移动元素的位置,所以不会导致迭代器失效。这里二师兄回答的倒是没有毛病,但是没有考虑到缓存问题。底层采用数组存储数据,所以它的空间局部性更好,对缓存更友好(被称为双向链表,和C中手写双向链表本质上没有大的区别。二师兄:并不会,因为在任意位置添加和删除元素只需要改变。在随机插入数据不会导致数据的搬移。二师兄:不是,GCC中的实现只有在。二师兄:与手写双向链表不同的是,

binarch的博客 375

【华为OD技术面试手撕真题】- C++手撕技术面试八股文(3)

【华为OD技术面试手撕真题】- C++手撕技术面试八股文(3) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2025e卷,od机试,2025E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2025华为od,如何备战华为od,华为od算法,华为od手撕代码,华为OD机试2025年最新题

KJ.JK 1万+

C++面试八股文快问快答のSTL篇

STL篇 vector的底层原理(此题本人踩坑,需重视) vector底层是一个动态数组,包含三个迭代器,start和finish之间是已经被使用的空间范围,end_of_storage是整块连续空间包括备用空间的尾部。 当空间不够装下数据(vec.push_back(val))时,会自动申请另一片更大的空间(1.5倍或者2倍),然后把原来的数据拷贝到新的内存空间,接着释放原来的那片空间[vector内存增长机制]。 当释放或者删除(vec.clear())里面的数据时,其存储空间不释放,仅仅是清空了里面的

谁吃薄荷糖 2498

华为od 面试八股文_C++_02_含答案

华为od 面试八股文_C++_02_含答案

MISAYAONE的博客 3121

C++ STL之deque详解:从使用到底层,再到面试八股

摘要:C++ STL deque详解 deque是一种双端队列容器,支持高效的两端操作(O(1))。它采用分段连续存储结构,由多个固定大小的内存块和中控指针数组组成,既不是完全连续也不是完全离散。特性包括: 支持快速随机访问(两步寻址) 两端插入/删除高效 中间操作较慢(O(n)) 相比vector没有capacity概念 提供完整迭代器支持(包括随机访问) 典型应用场景:需要频繁两端操作的队列/栈 面试要点:强调其分段连续的结构设计,解释为何两端操作高效而中间操作较慢,以及与vector/list的主要区

Rick_Theseusr的博客 378

C++八股文暗黑风格指南:高频考点与面试实战拆解

在C++岗位面试中,内存管理、智能指针、模板泛型、STL容器与多线程并发是绕不开的核心知识模块。理解shared_ptr控制块的生命周期、vector扩容机制、虚函数表布局以及std::move的本质,是检验候选人底层逻辑是否扎实的关键。面试官往往通过深挖这些基础概念,判断候选人在真实项目中能否定位性能瓶颈与bug根源。掌握结构化答题逻辑,先说结论再展开细节,并主动将理论知识点与项目经历挂钩,能显著提升面试表现。对于模板实例化时机、unordered_map迭代器失效、无锁编程中的ABA问题等易错细节,系统

weixin_31292729的博客 303

FPGA中的CMAC硬核与Interlaken硬核

CMAC硬核和Interlaken硬核是FPGA中两种重要的内置功能模块,它们分别在CNN推理和高带宽芯片到芯片接口方面发挥着关键作用。FPGA(Field Programmable Gate Array,现场可编程逻辑门阵列)中的CMAC硬核与Interlaken硬核是两种重要的内置功能模块,它们在FPGA设计中扮演着关键角色。需要注意的是,FPGA设计中的硬核选择不仅取决于硬核本身的性能,还需要考虑硬核与FPGA芯片其他部分的兼容性、功耗、成本等因素。Interlaken硬核。

weixin_41230430的博客 1481

大厂面试八股文——STL

文章目录STL理解STL空间适配器sort1.vetcor2.list双向链表3.deque双向队列3.1.stack()堆3.2.queue队列4.红黑树RB-tree4.1 set、multiset4.2 map、multimap5 hashtablehashtable(哈希表)vector和list的区别unordered_map和map的区别算法equal STL理解 ① 长久以来,软件界一直希望建立一种可重复利用的东西。 ② C++的面向对象和泛型编程思想,目的就是复用性的提升。 ③ 大多数情况下

xiaohu的博客 2148

用Typora画流程图和序列图:Mermaid语法实战教程(含常见报错解决)

本文是一份详细的Typora与Mermaid语法实战教程,教你如何在Markdown文档中高效绘制流程图和序列图。文章涵盖从环境配置、核心语法到复杂图表构建的全过程,并重点解析了常见报错原因与解决方案,助你将可视化图表无缝融入文档工作流。

weixin_29279101的博客 299

【小陈背八股-C++】Day04-大厂面试直击:Vector扩容机制,你真的懂STL容器吗?

🔥 面试必问:为什么vector扩容1.5倍而非2倍?emplace_back比push_back快在哪? 🔍 深度剖析:连续存储的vector如何保证性能?map红黑树为何比unordered_map更稳定? ⚡ 性能陷阱:动态数组与固定数组的使用禁区!不同场景下容器选择的黄金法则。 💡 实战技巧:从底层实现看懂容器行为,避免常见性能坑点,让你的C++代码效率提升一个量级! 🎯 无论你是面试突击还是性能优化,这篇指南将彻底改变你对STL容器的认知!

小陈为梦想而生 893

分布式 Agent 系统设计:高并发场景下的挑战与解决方案

分布式 Agent 系统由多个分布在不同节点上的智能 Agent 组成,这些 Agent 具有自主决策能力,能够通过通信协作完成复杂任务。每个 Agent 可以看作是一个独立的实体,具备感知环境、处理信息、执行动作的功能,它们相互协作,共同实现系统的整体目标。分布式 Agent 系统在高并发场景下面临着资源调度、通信延迟、状态一致性、容错处理和性能瓶颈等诸多挑战。通过采用动态资源分配、高效通信协议、分布式共识算法、冗余备份等解决方案,可以有效应对这些挑战,提高系统的性能、可靠性和可用性。

shuizhudan223的博客 1292

Halcon实战:5分钟搞定线序颜色检测(附完整代码解析)

本文详细介绍了如何使用Halcon在5分钟内实现工业级线序颜色检测的高效方案。通过机器视觉技术,结合实战项目经验,提供完整的代码解析和优化技巧,帮助开发者快速构建鲁棒性强、准确率高的检测系统,适用于电子制造和汽车线束等行业。

weixin_29098367的博客 441

C++面试八股文

1. 只在堆上生成对象将析构函数设置为私有:c++ 是静态绑定语言,编译器管理栈上对象的声明周期,为对象分配栈空间时,会先检查类的析构函数的访问性2. 只在栈上生成对象将new和delete重载为私有:在堆上生成对象使用new关键词,分为两个阶段:1. 使用new在堆上寻找可用内存 2.调用构造函数生成对象,new设置为私有,则第一步无法完成锁是一种思想,最终会落实到两种机制上:1.处理器提供的原子操作指令(CAS);2.内核提供的锁系统调用,在被锁住的时候会把当前线程至于睡眠(阻塞)状态。

gwl2115的博客 765

【专栏必读】王道考研408操作系统+Linux系统编程万字笔记使用说明及章节导航

王道408考研操作系统)第一章计算机系统概述-第一节1、2:操作系统概念、概念和特征1:理解fork的作用prinf("还没有执行fork函数的本进程为:%d\n" , getpid());//其返回值是pid类型的 sleep(1);if(ret > 0) //父进程返回的是子进程ID {printf("我是父进程,我的id是:%d,我的孩子id是%d\n" , getpid() , ret);sleep(1);} } else if(ret == 0) //子进程fork返回值是0 {.........

快乐江湖的博客 3万+

c++面试八股文

RAII,全称为 Resource Acquisition Is Initialization,中文名为“资源获取即初始化”,是 C++ 中常用的一种管理资源、避免资源泄漏的编程技术。RAII 技术基于 C++ 语言的对象生命周期原理,它通过在对象构造函数中获取资源,并在对象析构函数中释放资源的方式,来确保资源的正确管理。使用 RAII 技术,可以有效地避免因程序异常退出或者忘记释放资源等问题导致的内存泄漏、文件句柄泄漏、锁死等问题。

weixin_50012301的博客 1235

进阶06:C#连接TwinCAT 3使用ADS通讯

本文介绍了使用C#通过ADS协议与倍福TwinCAT3 PLC通讯的实现方法。主要内容包括:1)在两台电脑上安装TwinCAT3开发环境并建立网络连接;2)在TwinCAT中定义变量和结构体;3)使用C# Winform开发界面,通过TwinCAT.Ads.dll实现读写功能;4)实现主动读取和通知两种数据获取方式。详细说明了连接建立、变量定义、读写操作及事件通知的实现代码。该方案实现了对PLC寄存器数据的实时监控和操作,为工业控制系统的开发提供了参考。

weixin_38637405的博客 3688

RICHARDSON-LUCY 去卷积简介

Lucy去卷积1.泊松过程及联合概率分布2.极大似然估计参考文献 1.泊松过程及联合概率分布 首先假设相机接收光子生成图像的过程符合泊松分布。 因此,一次曝光过程中,某像素位置接收到iii个光子的概率p(i)p(i)p(i)为: p(i)=exp⁡(−λ)⋅λii!\qquad\qquad p(i)=\exp(-\lambda)\cdot\cfrac{\lambda^{i}}{i!}p(i)=exp(−λ)⋅i!λi​ 那么针对一张M∗NM*NM∗N的图像,所有像素的联合概率分布可以描述为: P(I)=∏e

驽马十驾,功在不舍;锲而不舍,金石可镂。 8694

C++面试八股勘误:常见错误结论与机制解析

在C++开发与面试准备中,许多流传的“八股结论”往往因编译器版本或标准演进而失真,例如constexpr是否必须在编译期执行、std::move是否真的移动对象、shared_ptr线程安全的边界等。理解这些机制背后的原理,不仅有助于应对C++面试中的追问,更能指导实际工程中写出高效且安全的代码。本文从对象模型、模板编译期与STL容器等高频误区切入,结合标准文档与编译器实测,逐条勘误常见错误结论,帮助开发者建立可验证的知识体系,避免被过时网文带偏。

dengjuanshou7445的博客 461

YOLOv5_DeepSORT_Pytorch训练自己的多目标跟踪模型

1 准备 环境配置:https://blog.youkuaiyun.com/weixin_50008473/article/details/115250986?spm=1001.2014.3001.5501 YOLOv5_DeepSORT_Pytorch代码地址: https://github.com/mikel-brostrom/Yolov5_DeepSort_Pytorch DeepSORT论文:https://arxiv.org/pdf/1703.07402.pdf 2 训练目标检测模型 训练自己的目标检测模

weixin_50008473的博客 1万+

C++——STL

STL相关八股文,整理不易!欢迎一键三连!本文参考了很多材料bibi上的千峰提供的文档以及小程序面试鸭里头的文档!

qq_42615475的博客 880

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C++实现动态顺序表:从核心原理到STL vector的底层剖析

顺序表是一种基于连续内存存储的线性数据结构,其核心原理是通过物理地址的连续性实现O(1)时间复杂度的随机访问。这种设计在计算机系统中广泛应用,因为它能充分利用CPU缓存预取机制,显著提升数据访问效率。然而,连续存储也带来了插入和删除操作需要移动大量元素的代价,体现了经典的空间与时间权衡思想。在工程实践中,动态顺序表通过内存的动态分配与扩容策略(如倍增扩容)来解决固定容量的局限性,这是理解现代容器库(如C++ STL)的基础。本文以C++为工具,深入探讨了动态顺序表的设计与实现,涵盖了内存管理、迭代器、异常安

311

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

C++ STL vector底层原理与模拟实现:从内存管理到迭代器失效

在C++编程中,容器是组织和管理数据的基础工具,其核心在于高效的内存管理和数据访问机制。动态数组作为最基础的线性结构,通过连续内存分配实现了O(1)的随机访问性能。C++标准模板库(STL)中的vector容器正是这一思想的典范,它封装了动态数组,并提供了自动扩容、边界检查等安全特性。理解其底层原理,特别是内存分配策略、深拷贝机制以及迭代器失效问题,对于编写高性能、健壮的C++代码至关重要。通过模拟实现vector,开发者可以深入掌握动态内存管理、对象生命周期控制以及异常安全等核心概念,这些知识在面试和工程

weixin_33393017的博客 285

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: C++ STL 之移动语义详解
下一篇: C++ STL 之智能指针详解:用法 × 原理 × 面试
Ricky_Theseus
博客等级 码龄3年 126粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ricky_Theseus

感谢大家,祝您生活愉快

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值