29 篇文章
1 Container 1.1 std::vector 迭代器在vector插入超过容量后,自动扩容时失效 引用语义在使用 span 时必须谨慎。将一个新元素插入 vector 中,该 vector 中保存了跨度所引用的元素。由于 span 的引用语义,若 vector 分配新的内存,会使所有迭代器和指向其元素的指针无效,所以重新分配也会使引用 vector 元素的 span 失效。span 指向了不再存在的元素。 出于这个原因,需要在插入前后都要仔细检查容量 (分配内存的最大元素数量)。若容量发生变化,则重新初始化 span .
2 Algorithm 2.1 std::transform std::transform applies the given function to the elements of the given input range(s), and stores the result in an output range starting from d_first.
3 Iterator 输入迭代器:只能用来读取指向的值;当该迭代器自加时,之前指向的值就不可访问。 std::istream_iterator 就是这样的迭代器。 前向迭代器:类似于输入迭代器,可以在指示范围迭代多次 std::forward_list 就是这样的迭代器。就像一个单向链表一样,只能向前遍历,不能向后遍历,但可以反复迭代。 双向迭代器:这个迭代器可以自增,也可以自减,迭代器可以向前或向后迭代。 std::list, std::set 和 std::map 都支持双向迭代器。 随机访问迭代器:与其他迭代器不同,随机访问迭代器一次可以跳转到任何容器中的元素上,而非之前的迭代器,一次只...
4 FileSystem 文件系统库提供对文件系统及其组件(例如路径、常规文件和目录)执行操作的工具。 文件系统库最初开发为boost.filesystem ,并作为技术规范 ISO/IEC TS 18822:2015发布,最终于 C++17 合并到 ISO C++ 中。目前,boost 实现在比 C++17 库更多的编译器和平台上可用。 如果对此库中的函数的调用引发文件系统竞争,即当多个线程、进程或计算机交错访问和修改文件系统中的同一对象时,则行为未定义。 4.1 定义 file:保存数据的文件系统对象,可以写入、读取或两者兼而有之。文件具有名称、属性,其中之一是文件类型: 目录:充当目录条...
5 View 通常若引用范围的元素修改,则视图的元素也会修改。 若视图的元素修改,则引用范围的元素也会修改。 视图通常用于在特定的基础上,处理基础范围的元素子集和/或经过一些可选转换后的值。例 如,可以使用一个视图来迭代一个范围的前五个元素 for (const auto& elem : std::views::take(coll, 5)) { ..
6 Span 💀 这段代码会导致未定义的行为,因为基于范围的 for 循环中存在一个 bug,在对临时对象的引用上进行迭代时会使用已经销毁的值 // for the last 3 returned elements: for (auto s : std::span{arrayOfConst()}.last(3)) // fatal runtime ERROR.
泛型算法 概述 不直接操作容器,遍历由两个迭代器指定的一个元素范围进行操作 迭代器令算法不依赖于容器 算法依赖于元素类型的操作 初识泛型算法 只读算法 find accumulate int sum = accumulate(vec.begin(),vec.end(), 0); // 第三个参数是和的初值 string sum = accumulate(v.cbegin(), v.cend(), string("")); // string定义了+运算符 count equal:确定两个序列是否保存相同的值,接受三个迭代器;假定每个元素在第二个序列中都有一个与之对应的元素(...
关联容器 关联容器支持高效的关键字查找和访问;主要的两个关联容器是map和set 使用关联容器 set和map的使用 map<string, size_t> word_cnt; set<string> exclude = {"The", "But"}; string word; while(cin >> word) // 只统计不在exclude中的单词 if(exclude.find(word) == exclude.end()) ++word_cnt[word]; 概述 关联容器不支持顺序容器的位置相关的操作,例如...
动态内存 静态内存保存局部static对象,类static数据成员以及任何定义在任何函数之外的变量 全局对象程序启动时分配,在程序结束时销毁 动态内存与智能指针 每个程序有一个内存池,叫做自由空间或堆 动态对象的生存期由程序来控制 智能指针负责自动释放所指向的对象 share_ptr允许多个指针指向同一个对象 unique_ptr则“独占”所指向的对象 weak_ptr是一种弱引用,指向shared_ptr所管理的对象 shared_ptr类 是一个模板,默认初始化的智能指针中保存着一个空指针 make_shared 最安全的分配和使用动态内存的方法 在动态内存中分配一个对象并初始化它;返回指...
拷贝控制 拷贝、赋值与销毁 拷贝构造函数 第一个参数是自身类类型的引用,所有其他参数均有默认值 逐个拷贝非static成员;内置类型成员直接内存拷贝;类类型成员,调用拷贝构造函数拷贝 string dots(10, '.'); // 直接初始化 string s(dots); // 直接初始化 string s2 = dots; // 拷贝初始化 string null_book = "99" // 拷贝初始化 拷贝初始化 “=” 一个对象作为实参传递给一个非引用类型的形参 从一个返回类型为非引用类型的函数返回一个对象 用花括号列表初始化一个数组中的元素...
重载运算和类型转换 基本概念 重载的运算符是成员函数时,this绑定到左侧运算对象;成员运算符函数的显式参数数量比运算对象的数量少一个 对于一个运算符函数来说,它或者是类的成员或者至少含有一个类类型的参数 // 调用了非成员函数 data + data2; operator+(data, data2); // 调用了成员函数 data1 += data2; data1.operator+=(data2); 使用与内置类型一致的含义 IO类型保持一致 如果定义了operator==,应该定义operator!= 包含一个内在的单序比较,定义operator <, operator>…...
OOP.
变量和基本类型 1.基本内置类型 算数类型和空类型 bool, char, wchar_t, char16_t, char32_t, short, int, long, long long, fliat, double, long double w_char_t确保可以存放机器最大扩展字符集中的任意一个字符 char16_t,char32_t为Unicode字符集服务 一般float 32bit,double 64bit,long double 96/128bit 带符号类型和无符号类型 int, short, long, long long前直接加unsigned signed char和u...
字符串、向量、数组 using声明 一般头文件不应该包含using声明 String 直接初始化和拷贝初始化 等性判断对字母的大小写敏感 如果表达式中使用size()(返回一个无符号整数),避免使用int 字面值和对象相加至少+号两边有一个是string对象 Vector 迭代器 begin():表示第一个元素, end():表示尾元素的下一个元素,指示的是根本不存在的尾后元素 ==, !=如果两个迭代器指向相同的元素或者都是同一个容器的尾后迭代器则相等 迭代器类型 iterator是可以操纵的类型 const_iterator能读取但不能修改该迭代器指向的元素值 任何改变vector容量的操...
表达式 左值和右值 C++表达式要么为左值要么为右值 赋值运算符需要一个左值作为左侧运算对象,得到的结果仍然是一个左值 取地址符:得到的指针是一个右值 内置解引用符和下标运算符,迭代器解引用符,string & vector的下标运算符均是左值 内置类型和迭代器的递增递减运算符作用于左值运算对象 递增和递减运算符 作用于左值运算对象,前置版本将对象本身作为左值返回;后置版本作为右值返回 不建议使用后置版本 类型转换 算数转换 整型提升:把小整数类型转换成较大的整数类型 其他隐式类型转换 数组转换成指针 指针的转换转换成bool 转换成常量 类类型定义的转换 string s,t = &...
语句 switch 内部变量定义,使用花括号;只定义在该块内 try语句块和异常处理 throw表达式 try{…}catch(runtime_error e){…} 标准异常 excception:头文件中定义了通用的异常类exception。只报告异常的发生,不提供额外的信息 stdexcept:定义了集中常用的异常类 new头文件定义了bad_alloc type_info头文件定义了bad_cast异常类型 异常类型只有一个what成员函数,返回值是一个C风格字符串 Header guards(include guard) 避免一个头文件被多次引用 int getSquareSides...
函数 参数传递 传值参数 实参的值不变 初始值被拷贝给变量 传指针 拷贝的是指针,两个指针不同,但指向相同的对象 可以改变实参的值 传引用参数 绑定了初始化它的对象 避免拷贝 函数不需要改变引用形参的值,声明成常量引用 const形参和实参 实参初始化形参时会忽略掉顶层const 尽可能使用常量引用 数组形参 void print(const char *cp); void print(const int *beg, const int *end); // 传递指向数组首部和尾部的指针 void print(const int ia[], size_t size); void print(in...
类 this指针 成员函数通过this指针访问调用它的那个对象 this形参是隐式定义的;this是一个常量指针 const成员函数 默认情况下,this的类型是指向类类型非常量版本的常量指针 需要将this声明为指向常量的指针 std::string isbn() const {return this->bookNo;} 构造函数 只有类没有声明任何构造函数时,编译器才会自动生成默认构造函数 =default含义 作用完全等同于之前使用的合成默认构造函数 class和struct 希望定义的类的所有成员是public时,使用struct 希望成员是private的,使用class 友元...
IO库 IO class IO对象无拷贝,无赋值:不能作为参数和返回值 读写一个IO对象会改变其状态,传递和返回的引用不能是const 条件状态 管理输出缓冲 程序崩溃,输出缓冲区不会被刷新 每个输出流都管理一个缓冲区 缓冲刷新 程序正常结束,作为main函数的return操作一部分,缓冲被执行 缓冲区满时,需要刷新缓冲 endl等操纵符,显示刷新缓冲区 设置unitbuf来清空缓冲区 一个输出流可能被关联到另一个流。这种情况下,读写被关联的流时,关联到的流的缓冲区会被刷新 endl:输出换行符,刷新缓冲区 flush:刷新缓冲区,不附加任何额外字符 ends:输出一个空字符,刷新缓冲区 co...
顺序容器 概述 vector, deque在内存中连续保存;list不支持<运算 通常,使用vector是最好的选择 随机访问元素,用vector或deque 容器中间插入或删除,用list或forward_list 头尾插入或删除,用deque 容器库 顺序容器几乎可以保存任意类型的元素;也可以保存容器的容器 // noDefault是一个没有默认构造函数的类型 vector<noDefault> v1(20, init); // 提供元素初始化器 vector<noDefault> v2(10); // 必须提供一个元素初始化器 容器操作 迭代器 迭代器范围由...
Makefile 使用条件判断 libs_for_gcc = -lgnu normal_libs = foo: $(objects) ifeq ($(CC),gcc) $(CC) -o foo $(objects) $(libs_for_gcc) else $(CC) -o foo $(objects) $(normal_libs) endif 使用函数 字符串处理函数 $(subst <from>,<to>,<text>) • 名称:字符串替换函数 • 功能:把字串 <text> 中的 <from> 字符串替换成 <to>...
并发与多线程编程 线程传值 使用 detach() 分离两个线程可能会导致主线程在子线程结束前就跑完了 char*变量在线程中地址相同;使用string类型引用来解决;创建 m_thread 对象的时候复制一份临时变量 隐式转换和显示转换 隐式转换,对象在子线程进行构造;如果detach后main线程先结束;直接失败 显示转换,对象的构建过程和拷贝过程都是在主线程中完成的,这就确保了子线程在使用该参数时是安全的 临时变量传参 如果传递int这种简单类型,推荐使用值传递,不要用引用; 如果传递类对象,要避免使用隐式类型转换,必须在代码中显式转换(相当于创建一个临时变量),然后在函数参数里,用引用...
并发组件的内部实现浅析
C++ 的异步执行方案历史演进,从标准库的 Future 和 Promise,到 Folly 的扩展封装,再到 C++26 中的 std::execution 和协程的结合,详细介绍了各个方案的原理和使用方法。
C++11 的线程和 C++20 的RAII线程
C++ 内存模型和基于原子类型的操作
C++ 中线程共享数据的保护方式
C++ 中的同步并发操作
非阻塞的数据结构实现方式