Comenzando con la depuración de gdb, una guía de alta calidad escrita por Daniel
Arquitectura de Computadores Un Enfoque Cuantitativo traducción pdf
Diseño de sistema de programación automática.
Plan de crecimiento del programador
Visualización dinámica de estructuras de datos y algoritmos.
Implementación en lenguaje C puro de estructuras de datos y algoritmos básicos.
Notas de la entrevista en informática
Notas de la entrevista en informática 2
proceso de código visual
Varias referencias de códigos de prácticas de ingeniería.
Guía práctica de concurrencia multiproceso de C ++
tutorial c/c++
Para aprender C++, ¿qué libros deberías leer paso a paso?
Catálogo de series de algoritmos y estructura de datos.
Después de completar estas 65 preguntas, la tasa de aprobación de la entrevista se duplicará sin problema.
experimento de código c ++
Búsqueda de código fuente en libros populares
Búsqueda de código fuente en inglés.
Índice de libros de programación chinos gratuitos
¡La entrevista de código es mejor y muy recomendable! ! ! ! !
notas de revisión de Nowcoder
Notas del examen LeetCode
Revisa C++ conmigo
Cinco ideas de algoritmos de uso común en Leetcode
Estructura de datos Blog Referencia Diagrama de árbol Cola
GitHub Pages+Jekyll para crear un blog personal
Conjunto de herramientas de rebajas
Sistema operativo Tsinghua github
Columna del blog Programación en entorno Linux
Columna del BlogProgramación de Redes Linux
Columna de blog para aprender C++ paso a paso
Lenguaje C de la columna del blog.
Fish C Studio C/C++/Python/Wed/Estructuras de datos y algoritmos
Programación de interfaz gráfica.
Notas del blog sobre el algoritmo de la entrevista
Algoritmo básico de Liu Guoping
CPP11 nuevo código especial de combate real
Nuevas funcionesConceptos y fragmentos de código de C++14/11/17
Un tutorial detallado sobre concurrencia de Cplusplus "Guía de programación concurrente de C++"
Una guía detallada sobre programación concurrente y multiproceso basada en los nuevos estándares C++ 11 C++ Concurrency In Action
Traducción al chino de la versión en inglés del "libro de cocina STL C ++ 17"
Aprendizaje de hash
Editor de Oracle Corporation Biblioteca de información de Oracle Solaris Studio 12.4 (chino simplificado) Guía del usuario de c/cpp Guía de computación numérica Analizador de código Analizador de rendimiento Analizador de subprocesos
Principios de compilación del Instituto de Tecnología de Harbin
Principio de compilación: implementación del analizador léxico
Tecnología de compilación Western Electric
Plantilla de escritura de libros en línea gitbook
Bibliografía de aprendizaje paso a paso.
svn crea un nuevo tronco y rama
git clone --recurse-submodules https://github.com/xxxxx.git
Tenga en cuenta que debe traer el parámetro --recurse-submodules al clonar; de lo contrario, la descarga estará incompleta.
1. c
2. c++
3. python
4. 汇编语言
5. 数据机构和算法 面试
6. 操作系统os
7. 单片机stm32 arduino Ti-msp430 树莓派 px4 arm
8. 数据挖掘
9. 人机工程学
10. 计算机科学
《Essential C++》
这是一本内容不多但很实用的C++入门书籍,强调快速上手与理解C++编程。
本书主要围绕一系列逐渐复杂的程序问题,以及用以解决这些问题的语言特性展开讲解。
你不只学到C++的函数和结构,也会学习到它们的设计目的和基本原理。
《C++ Primer》
本书对C++基本概念、技术、以及现代C++编程风格进行了全面而且权威的阐述,是C++初学者的最佳指南;
本书可以帮助你编写实用的程序,而无需首先精通每个语言细节。
对于中高级程序员,本书也是不可或缺的参考书。
《Effective C++》和《More effective C++》作者是Scott Meyers。
你应该熟读它们,并清楚地理解每个项目。
该书围绕55条准则,每一条都介绍了一个可让你写出更好的C++程序代码的方法,并以特别设计过的例子详加讨论。
《Exceptional C++(C++编程剖析)》和《More exceptional C++》
这两本书中都包含了40个C++编程问题,这些问题会让你磨练自己的技能,最终成为优秀的C++程序员。
这些问题是Herb Sutter精心挑选,与ISO/ANSI C++官方标准相一致,
帮助程序员在设计、架构和编码过程中保持良好的风格,从而使编写的C++软件更健壮、更高效。
《Inside the C++ object model(深度探索C++对象模型)》
本书专注于C++面向对象程序设计的底层机制,
包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承,
帮助你理解程序的底层实现,以便写出更高效的代码。
《The design and evolution of C++(C++语言的设计与演化)》
本书作者也是C++语言的设计者Bjarne Stroustrup,作者在书中综合性地介绍了C++的发展历史,
C++中各种重要机制的本质意义和设计背景,这些机制的基本用途和使用方法,
讨论了C++所适合的应用领域及其未来的发展前景,既没有忽略关键性的详情,又没有过多地陷入技术细节。
《The C++ standard library(C++标准程序库)》
这是标准模板库字典,你可以在本书中找到STL相关的一切知识。
本书焦点放在标准模板库、检查容器、迭代器、函数对象和STL算法上。
每一个元素都有深刻的呈现,包括其介绍、设计、运用实例、
细节解说、陷阱、意想不到的危险,以及相关类别和函数等。
《Effective STL》
这是Scott Meyers的第三本C++专著,也是学习STL最权威的书籍。
作者对书中的50个指导方针都作了详尽的分析,并配以示例。
通过这些规则,C++开发者可以最大限度地使用STL。
《Generic programming and the STL(泛型编程与STL)》
本书阐述了泛型程序设计的核心理念:concepts(概念)、modeling(模型)和refinement(改善),
并为你展示这些观念如何导出STL的基础概念:iterators(迭代器)、
containers(容器)和function objects(函数对象)。
按照本书所述,你可以把STL想象成一个由concepts组成的library,你将学习到STL正式结构并理解其强大的优势。
《Exceptional C++ style》
作者为Herb Sutter。本书同样提出了40个C++风格相关的问题
,对一些至关重要的C++细节和相互关系提出了新的见解,
为当今的关键C++编程技术(如泛型编程、STL、异常安全等)提供了新的策略,
帮助开发者在开销与功能之间、优雅与可维护性之间、灵活性与过分灵活之间寻找完美的平衡点。
《C++ template》
这是一本关于C++模板的完整的参考手册和教程,它强调模板的使用实践,包含了现实世界中的例子。
每个C++程序员都应该好好读一读这本书。
《Modern C++ design(现代C++设计)》
作者Andrei Alexandrescu为C++程序员打开了一个新的局面。
本书提供了一些针对软件设计的前沿方法,如联合设计模式、泛型编程,
使程序员可以编写有表现力的、灵活的、高度可重用的代码。
《Thinking in C++(C++编程思想)》
C++ 领域权威著作,介绍了C++实用的编程技术和最佳的实践方法。
Webbench是一个在Linux下使用的非常简单的网站压测工具。
它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,
最多可以模拟3万个并发连接去测试网站的负载能力。
Webbench使用C语言编写, 代码实在太简洁,源码加起来不到600行。
Página de inicio del proyecto: http://home.tiscali.cz/~cz210552/webbench.html
tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),
附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。
Página de inicio del proyecto: http://sourceforge.net/projects/tinyhttpd/
cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。
cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。
其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。
Página de inicio del proyecto: http://sourceforge.net/projects/cjson/
cmockery是google发布的用于C单元测试的一个轻量级的框架。
它很小巧,对其他开源包没有依赖,对被测试代码侵入性小。
cmockery的源代码行数不到3K,你阅读一下will_return和mock的源代码就一目了然了。
主要特点:
免费且开源,google提供技术支持;
轻量级的框架,使测试更加快速简单;
避免使用复杂的编译器特性,对老版本的编译器来讲,兼容性好;
并不强制要求待测代码必须依赖C99标准,这一特性对许多嵌入式系统的开发很有用
Página de inicio del proyecto: http://code.google.com/p/cmockery/downloads/list
libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。
其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理。
基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。
Página de inicio del proyecto: http://software.schmorp.de/pkg/libev.html
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。
它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态数据库驱动网站的速度。
Memcached 基于一个存储键/值对的 hashmap。
Memcached-1.4.7的代码量还是可以接受的,只有10K行左右。
Página de inicio del proyecto: http://memcached.org/
Lua很棒,Lua是巴西人发明的,这些都令我不爽,但是还不至于脸红,最多眼红。
让我脸红的是Lua的源代码,百分之一百的ANSI C,一点都不掺杂。
在任何支持ANSI C编译器的平台上都可以轻松编译通过。我试过,真是一点废话都没有。
Lua的代码数量足够小,5.1.4仅仅1.5W行,去掉空白行和注释估计能到1W行。
Página de inicio del proyecto: http://www.lua.org/
SQLite是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。
其特点是高度便携、使用方便、结构紧凑、高效、可靠。足够小,大致3万行C代码,250K。
Página de inicio del proyecto: http://www.sqlite.org/.
UNIX V6 的内核源代码包括设备驱动程序在内 约有1 万行,这个数量的源代码,初学者是能够充分理解的。
有一种说法是一个人所能理解的代码量上限为1 万行,UNIX V6的内核源代码从数量上看正好在这个范围之内。
看到这里,大家是不是也有“如果只有1万行的话没准儿我也能学会”的想法呢?
另一方面,最近的操作系统,例如Linux 最新版的内核源代码据说超过了1000 万行。
就算不是初学者,想完全理解全部代码基本上也是不可能的。
Página de inicio del proyecto: http://minnie.tuhs.org/cgi-bin/utree.pl?file=V6
NetBSD是一个免费的,具有高度移植性的 UNIX-like 操作系统,
是现行可移植平台最多的操作系统,可以在许多平台上执行,
从 64bit alpha 服务器到手持设备和嵌入式设备。
NetBSD计划的口号是:”Of course it runs NetBSD”。
它设计简洁,代码规范,拥有众多先进特性,使得它在业界和学术界广受好评。
由于简洁的设计和先进的特征,使得它在生产和研究方面,
都有卓越的表现,而且它也有受使用者支持的完整的源代码。
许多程序都可以很容易地通过NetBSD Packages Collection获得。
Página de inicio del proyecto: http://www.netbsd.org/
sizeof有三种语法形式,如下:
1) sizeof( object ); // sizeof( 对象 );
2) sizeof( type_name ); // sizeof( 类型 );
3) sizeof object; // sizeof 对象;
与计算机类型有关,32为计算机,地址长度为4字节
64位的计算机,地长度为 8字节
这里的指针包括所有类型的指针:
字符指针、整形指针、字符串指针、指针的指针、函数指针、数组指针等。
数组的sizeof值等于数组所占用的内存字节数,如:
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符串末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int,这里int为4字节)
// 这里注意 &a2和a2的值是相等的,都是a2[0]的地址
// 但是 &a2 的类型为 int *[10]
// 而a2的类型为 int* p
//数组元素数量求取
int c1 = sizeof( a1 ) / sizeof( char ); // 总长度/单个元素的长度(知道元素类型)
int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 总长度/第一个元素的长度(不知道元素类型)
需要看编译器是几个字节对齐 的,一般为4字节对齐
typedef struct
{
int a; // 占据第一个4字节
char b; // 占据第二个4字节
}A_t;
typedef struct
{
int a; // 占据第一个4字节
char b;// 占据第二个4字节中的第一个字节
char c;// 占据第二个4字节中的第二个字节
}B_t;
typedef struct
{
char a;// 占据第一个4字节的第一个字节
int b; // 占据第二个4字节
char c;// 占据第三个4字节的第一个字节
}C_t;
referencia efectiva de blog stl
判断两个浮点数a和b是否相等时,不要使用 a==b ,
应该判断两者的绝对值之差fabs(a-b)是否小于一个阈值 ,如1e-9
if(fabs(a-b) < 1e-9)
应该先将char 强制转换为 unsigned char后在用作下标。
char index_;
unsigned char index = (unsigned char)index_;
vector 和 string 定义的对象 会自动 构造和析构,不用担心内存泄漏的问题
使用new[]分配的动态数组,需要配合 delete[]类释放会造成内存,否者会造成内存泄漏的问题
例如 定义一个二维数组,指针的指针
自己用new实现:
int * * arr_pp new int * [ row_num ]; // 定义一个存储指针的数组的指针 行数
for ( i = 0 ; i < row_num ; ++ i )
arr_pp [ i ] = new int [ col_num ]; // 一个一个new 指针每一行是一个行向量的指针
用 vector实现,一行代码搞定,还不到担心内存泄漏的问题
vector < vector < int >> v_i2 ( row_num , vector < int > ( col_num , 0 )); //初始化为一个0矩阵
vector < int > m ;
m . reserve ( 1000 ); //提前保留1000的内存
//使用 reserve 避免不必要的重新分配
int val = 1024 ; //整形变量
int & refVal = val ; // 整形引用 refVal 指向 val ,是val的另一个名字,
// 引用必须被初始化,引用不是对象,只是为所存在的对象起的一个别名。
refVal = 2 ; // 把2 赋值给refVal 也就是 赋值给了 val
int i = refVal ; // 相当于 i = val;
int & refVal2 = 10 ; // 错误,非常量引用只能绑定(bind)在对象向,
// 不能与字面值或某个表达式的计算结果绑定在一起, 且引用的类型 必须和 对象的类型一致
const int & rci = 10 ; // 常量引用可以绑定到 字面值 非常量 一般表达式
double dval = 3.14 ; // 浮点数
int & refVal3 = dval ; // 错误,引用的类型 和 对象 必须一致
int ival = 42 ; // 整数
int * p = & ival ; // 指针定义 p存放 ival对象存放的地址,也即是 p 指向 变量 ival的指针 &ival 为取的 ival变量的 存储地址
double dval = 3.14 ; // 浮点数
double * pd = & dval ; // double 类型 指针
double * pd2 = pd ; // pd存放 的是 dval存放的地址
int * pi = pd ; // 错误, 指针pi 的类型 和 右边指针对象 类型 不匹配
pi = & dval ; // 错误, 视图把 double 类型对象的地址 给 int类型的指针 错误 左右两边类型 必须匹配
Utilice el puntero para acceder al objeto para obtener el valor almacenado en el carácter de desreferencia de dirección para acceder al objeto.
int ival = 42 ; //整形 变量
int * p = & ival ; //指针变量定义初始化, p 存放着 变量ival 在内存中的地址
std:: cout << * p ; // 表达式里 *p 为 解引用 取的p存放的地址 指向的值
int & ref_i = ival ; // 引用声明定义, ref_i 是一个引用
int * p ; //指针声明定义,p是一个指针
p = & ival ; // 表达式 p为指针(地址),&val 为取的 val 地址
* p = ival ; //表达式 *p 相当于 ival *是一个解引用
int & ref_i2 = * p ; // &ref_i2 为引用定义 *p 相当于 ival, *是一个解引用
puntero nulo
int * p1 = nullptr ; // 等价于 int *p1 = 0; 空指针 p1 不指向 任何 对象
int * p2 = 0 ; // 空指针 等价于 int *p1 = 0;
int * p3 = NULL ; // 空指针 等价于 int *p1 = 0;
int zero = 0 ;
int * p4 = zero ; // 错误,不能把 int 变量直接赋值 给指针
int i = 42 ;
int * pi1 = 0 ; // pi1 被初始化为空指针,但没有指向 任何对象
int * pi2 = & i ; // pi2 被初始化,存有 i 的地址
int * pi3 ; // 定义 未初始化
pi3 = pi2 ; // pi3 和 pi2指向同一个 对象 i
pi2 = 0 ; // 现在 pi2 被赋值为 空指针 不指向任何对象 指针被改变, 指向的对象不变
pi2 = & i ; // 现在 pi2 又指向 i
* pi2 = 0 ; // 指针pi2 没变 , *pi2 被改变 即pi2指向的对象 i 发生了变化
Cuando se utiliza un puntero como condición es un puntero nulo, el valor lógico es Falso y otros punteros que apuntan a un objeto (punteros distintos de cero) tienen un valor lógico de verdadero.
Igualdad == operador No igual != operador
Un puntero de tipo void* puede apuntar a cualquier tipo de dirección y puede almacenar cualquier tipo de dirección.
Se utiliza como parámetro de función, es necesario cuando se usa en el cuerpo de la función y se convierte en un puntero al tipo real pasado.
double obj = 3.14 , * pd = & obj ; // double 类型 的变量 double类型的指针
void * pv = & obj ; // obj 可以是任意类型的对象
pv = pd ; // pv 可一存放任意类型的指针(地址)
double * pd = ( double * )( pv ); // void* 类型的指针 强制转化成 double* 类型的指针
Definir múltiples variables
int i = 1024 , * p = & i , & r = i ; //i是整形变量 p是一个整形指针 r是一个整形引用
int * p1 , p2 ; // * 仅仅修饰 p1 ,即p1是 指向整形的指针 p2是整形变量
int * p1 , * p2 ; // p1 和 p2 都是指向 整形的指针
puntero a puntero
int ival = 1024 ;
int * pi = & ival ; //指向整形变量的指针
int * * ppi = & pi ; //指向整形指针的指针 ppi ---> pi ------> ival
std:: cout << ival << "n" // 直接输出 变量值
<< * pi << "n" // 1次解引用 得到变量值
<< * * ppi << "n" ; //2次解引用 的到变量值
Una referencia a un puntero es un alias para un objeto de puntero. Una referencia no es un objeto. Un puntero a una referencia no existe.
int i = 42 ; //整形对象
int * p ; //指向整形类型的指针
int * & r_p = p ; //引用r_p的类型为 整形的指针引用int*&,r_p 是指针p的一个别名
//从右向左 离变量最近的符号为 & 即为 引用,* 引用的为 指针类型
r_p = & i ; // 相当于 p = &i p 指向 i
* r_p = 0 ; // 相当于 *p = 0 即 i =0 改变了指针指向对象的值
// 这里 *p *解引用指针的类型其实相当于 原变量的别名 引用
Después de modificar la variable, puede evitar que se modifique.
const int bufSize = 512 ; //初始化常量 一旦创建后就不能被修改
bufSize = 1024 ; // 错误,常量不能被赋值
const int i = get_size (); // 一个函数赋值 运行时初始化
const int j = 42 ; //编译时初始化
const int k ; //错误,常量定义式必须初始化
double dvel = 3.14 ; // 也可以由其他类型变量 强制转换成 常量
const int ci = dvel ; // 由double类型变量 强制转换成 整形常量 3
extern const int bufSize = 1024 ; //定义了一个变量,想在其他文件也使用 bufSize 必须在定义之前 加extern
extern const int bufSize ; // 另一个文件中 声明 bufSize 后 就可以使用了
Una referencia vinculada a una constante. Una referencia a una constante es una referencia a una constante. El alias de una constante no se puede modificar. La referencia constante no existe y la referencia constante no es un objeto.
const int c_i = 1024 ; // 常整数
const int & r_c_i = c_i ; // 常整数 c_i 的 引用(别名)
r_c_i = 42 ; // 错误r_c_i 是常量引用 不能被修改
int & r_c_i2 = c_i ; //错误 常整数 不能赋值给 int变量 左右两边类型必须一样
Permite vincular una referencia constante a un objeto no constante, un literal o incluso una expresión general.
int i = 52;
const int &r1 = i; // 允许将 常量引用 const int & 绑定到 int变量上
const int &r2 = 42;// 绑定到 字面值上
const int &r3 = r1 * 2;// 绑定到一个 表达式上
int &r4 = r1 * 2;// 错误,r4是非常量 引用,只能绑定到 其对应类型的对象上
double dval = 3.14;//浮点数
const int &ri = dval;//常量引用 绑定到 非常量上
//相当于 先把 非常量转化成常量 强制类型转换 常量引用实际上绑定了一个临时变量
const int temp = dval;//
int i = 42;// int 变量
int &r1 = i;// 整数变量引用 r1为 i 的别名
const int &r2 = i;//常量 引用 r2 绑定到 变量 i上
r1 = 0;// 相当于 i =0
r2 = 0;// 错误 r2 时常量引用 不允许改变
Puntero a constante const int * El valor señalado por el puntero no se puede cambiar, es decir, *p no se puede asignar ni cambiar.
const double pi = 3.14 ; //双精度 浮点型 常量
double * ptr_d = & pi ; // 错误,浮点型变量指针 不能绑定一个 常量的存储地址
const double * ptr_d_c = & pi ; // 双精度常量 针 ptr_d_c 指向一个 双精度常量
* ptr_d_c = 42 ; // 不能给 pi 赋值 指向常量的指针的解引用相当于 绑定的常量 ,因此不能赋值
doubel dvel = 3.14 ; //双精度变量
ptr_d_c = & dvel ; //允许 常量指针ptr_d_c 指向一个变量dvel 但是不能通过 常量指针ptr_d_c 修改变量dvel
Puntero constante *const El puntero en sí no se puede cambiar, es decir, el puntero p no se puede cambiar, pero el objeto al que apunta no tiene ningún efecto.
int errNumber = 0 ; //
int * const conpErr = & errNumber ; // * 可变指针 *const 常量指针不可变
// 指向整形的 常量指针,conpErr 一直指向 errNumber
* conpErr = 3 ; //相当于 errNumber = 3
const double pi = 3.14 ; //
const double * const cd_cp = & pi ; //指向 常量的常量指针,
// 即 指针本身cd_cp不能变, 其指向的值 *cd_cp也不能变
La expresión constante es una cantidad/fórmula que se puede determinar en el momento de la compilación constexpr int ce = 20;
const int * p = nullptr ; // 指向整形常量 的指针
constexpr int * p = nullptr ; // 指向整形变量的 常量指针
// constexpr 声明中出现 指针 仅仅说明 指针为常量指针
int * const p = nullptr ; //指向 整形变量的 常量指针
const int * const p = nullptr ; // 指向 整形常量 的常量指针
constexpr const int * p = nullptr ; // 指向 整形常量 的常量指针
constexpr int ci = 42 ; // ci 是整形常量
int j = 0 ;
constexpr int * pci = & j ; // 指向整形的 常量指针
typedef double wages ; // wages 是double类型的 同义词
typedef wages base , * p ; // base 也是double类型的 同义词。 p是double * 的同义词
wages d_money = 1.00 ; //等有价于 double d_money = 1.00
p p_dmoney = & d_money ; //等价于 double *p_dmoney = &d_money;
cout << p_dmoney << endl ;
// 别名声明 alias declaration
using SI = Sales_Item ; // SI 是 Sales_Item 的 同义词
SI item ; //等价于 Sales_Item item;
// 指针、常量const 类别别名
typedef char * pstring ; // pstring等价于 char * 指向char 的指针(是指针)
const pstring cstr = 0 ; // cstr是指向 char 的 常量指针
// !!!!不是指向常量字符的 指针 不能直接替换 const修饰的主语是指针
const pstring * ps ; // ps是一个指针 它指向的对象 是 指向char的常量指针
auto item = val1 + val2 ; //item 初始化为 val1 和 val2相加的结果 类型 相同
// 一条语句定义多个变量时,各变量类型必须一致
auto i = 0 , * p = & i ; //正确 i是整数, p是指向整形的指针
auto sz = 0 , pi = 3.4 ; // 错误 sz 和 pi 类型不一致
// 引用 指针 常量 与 auto
int i = 0 , & r = i ; //r是i的别名 int类型
auto a = r ; // a 是一个整形数
// auto 会忽略掉 顶层const
const int ci = i , & cir = ci ; // 常整数
auto b = ci ; // b是一个整数,ci的顶层 const(最外层修饰 为顶层)特性被忽略
auto c = cir ; // c是一个整数,ci的顶层 const特性被忽略
auto d = & i ; // d是一个指向整形的指针
auto e = & ci ; // e是一个指向整形常量的指针 const
// 外又被 取地址符号修饰,所以这里的 const是 底层const 不被忽略
// 如果希望 auto 推断出的类型是 一个顶层 const,需要在其前面 明确指出
const auto f = ci ; // ci的推演类型是 int ,f是 const int
// 将引用设置为 auto 还按之前的初始化规则 保留 顶层 const
auto & g = ci ; // g 是一个 整形常量的 引用 (别名)
auto & h = 42 ; // 错误,非常量 引用 不能绑定 到 字面值
const auto & j = 42 ; // 正确, 常量引用可以绑定到 字面值
// 将 指针设置为 auto, 也按之前的初始化规则 保留顶层 const
auto * k = & ci ; // k为指向 整形常量的 指针
auto * l = 0 ; // l为空指针
const auto * m = & ci ; // m 为 指向整形常量的 常量指针
int i = 1024 ;
const int c_i = i ;
auto b = c_i ; // b是一个 整数 ,c_i的 顶层 const被忽略
auto e = & c_i ; // e 是一个 指向 整形常量的引用 这里的const是底层const 不被忽略
auto k = c_i , & ll = i ; // k 是整数, ll 是一个整数引用
auto k = c_i , & o = c_i ; // 错误,k 是整数变量 o是一个整数常量引用 类型不一致
auto & m = c_i , * p = & c_i ; //正确 m是整数常量引用,p是指向整数常量的指针
auto n = & c_i , * p = & c_i ; // 正确 n是整数常量 引用(底层const,不被忽略) p是指向整数常量的指针
decltype ( f ()) sum = x ; // sum 的类型为 函数 f() 的返回值类型 初始化为 x 就像 int sum = x; 一样
const int ci = 0 , & cj = ci ; // ci 整形常量 cj 整形常量的引用
decltype ( ci ) x = 0 ; // x的类型 同ci 是 整形常量 const int 不忽略 顶层 const
decltype ( cj ) y = x ; // y的类型 同cj 是 整形常量的引用 const int & y绑定到x上
decltype ( cj ) z ; // 错误 z是一个 引用 ,必须初始化
// decltype和引用 指针
int i = 42 , j = 12 , * p = & i , & r = i ;
decltype ( r ) a = j ; // a的类型和r的类型一致,为整数的引用 int& a绑定到j上
decltype ( r + 0 ) b ; //正确 加法的结果为 整形 int 因此 b为整形, 这里只定义 没有初始化
decltype ( * p ) c ; // 错误 其实*p 解引用指针 相当于i的别名 也就是引用
// 所有这里 c的类型为 整数引用 int &,是个引用,必须初始化
// decltype 的表达式如果 加上括号,得到的结果将是引用
decltype ( i ) e ; // e 是一个未初始化的 整形变量
decltype (( i )) d = e ; // d是一个 整数的引用 绑定到 整形变量 e上 双层引用括号 的结果 永远都是
// 赋值表达式 也会产生 引用 引用的类型就是 等式左边变量的类型 如果 i是int i = x的类型是 int&
string str ( "some string" );
for (auto c : str ) // auto自动推断类型
cout << c << endl ;
// 范围for 引用 改变 内容
string s ( "Hello World!!!" );
for ( auto & c : s ) // c是 字符串中每个元素的一个别名
c = toupper ( c ); //变成大写
cout << s << endl ;
El tipo de subíndice de la cadena es string::size_type. El número sin signo se puede obtener mediante decltype(s.size()). .
// 第一个字符改为大写
string s ( "some string" );
if (! s . empty ())
s [ 0 ] = toupper ( s [ 0 ]); //第一个字符改为大写 在 cctype头文件中
// 第一个单词改为大写
for ( decltype ( s . size ()) index = 0 ;
index != s . size () && ! isspace ( s [ index ]; ++ index ))
s [ index ] = toupper ( s [ index ]);
Debido a que vector puede almacenar cualquier tipo, necesita saber de antemano qué tipo de objeto se almacena. vector ivec vector<vector >;
// 初始化方式
vector < int > ivec ( 10 , -1 ); // 直接初始化 10个元素 全为 -1
vector < int > ivec2 = ivec ; //拷贝初始化
vector < int > ivec3 { 10 }; //一个元素 10
vector < int > ivec3 { 10 , 1 }; //两个元素 10 和 1
vector < string > svec { "a" , "an" , "the" }; //列表初始化 直接方式
vector < string > svec2 = { "a" , "an" , "the" }; //列表初始化 拷贝方式
// 默认初始化
vector < int > ivec ( 10 ); // 10个元素,每个值都是0
vector < string > svec ( 10 ); // 10个元素,每个值都是空 string 对象
vector < string > svec2 { 10 }; // 10个元素,每个值都是空 string 对象
vector < string > svec3 { 10 , "hi" }; // 10个 "hi"元素
vector < string > svec3 ( 10 , "hi" ); // 10个 "hi"元素
// 使用 .push_back() 添加元素
vector < int > ivec2 ; //空vec对象
for ( int i = 0 ; i != 100 ; ++ i )
ivec2 . push_back ( i ); // 一次把整数值 放到 ivec2尾部 结束后 ivec2有100个元素 0~99
// 实时添加 string 元素
string word ;
vector < string > text ; //空对象
while ( cin >> word )
text . push_back ( word ); // 把word添加到 text 后面
//使用范围for + 引用 访问 并改变vector元素
vector < int > iv { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; // 列表直接初始化
for (auto & i : v ) // 对于v中每个 元素的 引用 需要改变其值
i *= i ; // 变成原来值 的 平方
for (auto i : v ) // 仅读取其中的变量
cout << i << " ";
cout << endl ;
// vector 对象大小 类型为size_type
vector < int > :: size_type se = iv . size ();
// 使用索引[] 访问 计算vector对象元素索引 统计各个分数段上 出现的 成绩个数
// 索引不能添加元素
vector < unsigned > scores ( 11 , 0 ); //11个分数段, 0~9,10~19,...,90~99,100 计数值全部初始化为0
unsigned grade ;
while ( cin >> grade ){
if ( grade <= 100 ) ++ scores [ grade / 10 ];
}
// cin 读入一组词 改成大写 存入 vector中 #include <cctype> 使用toupper()
vector < string > sv ;
string word1 = "qwe" ;
cout << word1 << endl ;
while ( cin >> word1 ){
for (auto & c : word1 ) c = toupper ( c );
sv . push_back ( word1 );
cout << word1 << endl ; vector
}
// 修改 字符串 第一个元素为大小字符
string s ( "some string" );
if ( s . begin () != s . end ()){ //确保 s非空
auto it = s . begin (); // it 指向 s的第一个字符 类似指针 的作用
* it = toupper ( * it ); // 将当前字符改写成大写形式 *it 解引用迭代器 得到其所指向的 对象 是其指向对象的别名 引用
}
// 字符串的第一个单词 改写成大写
for (auto it = s . begin (); it != s . end () && ! isspace ( * it ); ++ it )
* it = toupper ( * it );
// 迭代器类型 iterator (具有读写功能) const_iterator 具有 读功能 不具有写功能
// 对象为常量 只具有常量类型的迭代器 const_iterator 对象为变量具有 iterator 和 const_iterator
vector < int > :: iterator it ; // 迭代器 it 可以读写 vector<int> 类型容器 的元素
string :: iterator it2 ; // it2 可以读写 string对象 中的字符
vector < int > :: const_iterator it3 ; //it3只能读元素,不能写元素
string :: const_iterator it4 ; //it4只能读字符,不能写字符
// cbegin() cend() 返回 常量 迭代器 仅能读取 容器元素 不能修改
vector < int > iv ; // 变量
const vector < int > civ ; // 常量
auto it1 = iv . begin (); // it1的类型为 vector<int>::iterator 能读写iv的元素
auto it2 = iv . cbegin (); // it2的类型为 vector<int>::const_iterator 能读iv的元素 不能修改 iv的元素
auto it3 = civ . begin (); // it3的类型为 vector<int>::const_iterator 能读civ的元素 不能修改 civ的元素
// 访问 容器元素对象的 成员函数 (*it).empty 等同于 it->empty() 解引用 和成员访问
vector < string > text ;
for (auto it = text . cbegin (); it != text . cend () && ! it -> empty (); ++ it )
cout << * it << endl ;
// 迭代器 运算
auto mid = iv . begin () + iv . size ()/ 2 ; //指向容器的中间位置
if ( it < mid ) // 处理前半部分元素
// 两个迭代器相减 得到的类型为 带符号整数 difference_type
// 常规二分查找算法
// 升序数组 查找的元素 范围开始 结束
int BinarySearch ( int * array , int key , int low , int high )
{
int mid ;
while ( low <= high ) // 缩小范围
{
mid = ( low + high ) / 2 ; //更新中间元素的 下标
if ( key == array [ mid ]) //中间元素是否 等于所查找的元素
return mid + 1 ; //相等 返回元素下标
else if ( key < array [ mid ]) //所查元素 比 中间元素小 则在 前区间查找
high = mid - 1 ; //将区间 右侧 退后 到 中间元素下标前一个元素 搜索 范围为 low,mid-1
else //所查元素 比 中间元素大 则 在后区间查找
low = mid + 1 ; //将区间 左测 提至 中间元素下标后一个元素 搜索 范围 mid+1,high
}
return 0 ;
}
// 使用迭代器完成二分查找
vector < int > text // 升序容器
auto b = text . begin (), e = text . end (); //起始 结束位置
auto mid = b + ( e - b )/ 2 ; //中间位置
while ( low <= end && * mid != key ){
if ( key < * mid ) e = mid - 1 ; //所查元素 比 中间元素小 则在 前区间查找
else b = mid + 1 ; // 所查元素 比 中间元素大 则 在后区间查找
mid = b + ( e - b )/ 2 ; //更新 中间位置
}
// 使用索引[] 访问 计算vector对象元素索引 统计各个分数段上 出现的 成绩个数
// 索引不能添加元素
vector < unsigned > scores ( 11 , 0 ); //11个分数段, 0~9,10~19,...,90~99,100 计数值全部初始化为0
unsigned grade ;
while ( cin >> grade ){
if ( grade <= 100 ) ++ scores [ grade / 10 ];
}
// 使用迭代器 访问 计算vector对象元素索引 统计各个分数段上 出现的 成绩个数
vector < unsigned > scores ( 11 , 0 ); //11个分数段, 0~9,10~19,...,90~99,100 计数值全部初始化为0
unsigned grade ;
auto it0 = scores . begin ();
while ( cin >> grade ){
auto it = it0 + grade / 10 ;
if ( grade <= 100 ) ++ * it ;
}
Las matrices son similares a la biblioteca estándar de tipo vector, que almacena contenedores de objetos del mismo tipo. Es necesario acceder a los objetos a través de su ubicación. A diferencia del vector, el tamaño de la matriz se determina y no se modifica, y los elementos no se pueden agregar a la matriz a voluntad. Las matrices no permiten la copia, mientras que los vectores permiten la copia. Tenga en cuenta que el nombre de la matriz es equivalente a la dirección del primer elemento de la matriz ia[10] ia === &ia[0]
constexpr unsigned sz = 42 ; //constexpr修饰,常量表达式
int arr [ 10 ]; //字面值常量初始化 含有10个整数的数组
int arr2 [ sz ]; //常量表达式初始化 含有42个个整数的数组
int * parr [ sz ]; //常量表达式初始化 含有42个指向整数的指针的数组
定义时必须指定数组类型,不能由auto来推断
不存在引用的数组,引用不是对象!!!
string nums [] = { "one" , "two" , "three" }; // 数组元素是string对象
string * sp = & nums [ 0 ]; // p指向nums的第一个元素
string * sp2 = nums ; // 等价于 string *sp2 = &nums[0]
auto sp3 ( nums ); //sp3 是一个string指针,指向nums的第一个元素
// 而decltype关键字 声明的 不发生上述转换
decltype ( nums ) sa = { "two" , "three" , "four" }; //sa 是一个 含有3个string对象的 数组
## 【2】 Inicializar explícitamente elementos de matriz
const unsigned sz = 3 ; //
int ia1 [ sz ] = { 0 , 1 , 2 }; //列表初始化 含有3个元素
int ia2 [] = { 0 , 1 , 2 }; //维度为3
int ia3 [ 5 ] = { 0 , 1 , 2 }; //等价于 {0, 1, 2, 0, 0}
// 字符数组
char ca1 [] = { 'C' , 'P' , 'P' }; //列表初始化
char ca2 [] = { 'C' , 'P' , 'P' , ' ' }; //含有显式的 空字符
char ca3 [] = "CPP" ; //字符串字面值初始化 自动添加表示字符串结束的空字符
// string 对象初始化 字符数组
string s ( "Hello World" );
const char * str = s . c_str (); // 用string对象初始化 字符数组 需要使用 c_str() 方法 最好再重新拷贝一份
// 数组 初始化 vector 对象
int i_arr [] = { 1 , 2 , 3 , 4 , 5 , 6 };
vector < int > ivec ( begin ( i_arr ), end ( i_arr )); //全部副本
vector < int > sub_ivec ( i_arr + 1 , i_arr + 4 ); // 包含 {2, 3, 4, 5}四个元素
// 不允许拷贝和赋值
char ca4 = ca3 ; // 错误
// 复杂的数组声明定义
int * parr [ 10 ]; // 是数组,包含10个整形指针的数组
int & rarr [ 10 ] = ?; //错误,不存在 引用数组,引用不是对象
int ( * Parray )[ 10 ] = & arr ; //是指针,指向一个含有10个整数的数组
int ( & Rarray )[ 10 ] = arr ; //是引用,引用一个含有10个整数的数组
//下标访问修改元素
unsigned score [ 11 ]; //11个分数段
unsigned grade ;
while ( cin >> grade ){
if ( grade <= 100 ) ++ score [ grade / 10 ]; //对应段 计数+1
}
// 范围for 访问修改所有元素
for ( auto i : score ) //可以设置为 引用就可以修改元素了
cout << i << " ";
cout << endl ;
// 指针访问数组
int iarr [] = { 0 , 1 , 2 , 3 , 4 }; //含有5个元素
int * pi = iarr ; //指向第一个元素的指针 iarr[0]
int * pi2 = iarr + 2 ; //指向第三个元素的指针 iarr[2]
auto num = end ( iarr ) - begin ( iarr ); // num的值是5 就是iarr包含元素的数量
// ptrdiff_t 类型 是signde类型 结果可能为负
++ pi ; //指向第二个元素 iarr[1]
j = pi [ 1 ]; // 等价于 *(p+1),就是 iarr[2], 就是 2
k = pi [ -1 ]; // 等价于 *(p-1),就是 iarr[0], 就是 0
pi + 3 ; //指向最后一个元素
* pi ; //第二个元素 4
int last = * ( iarr + 4 ); // 等价于 last = iarr[4];
int * end = & iarr [ 6 ]; //指向尾后的位置 到达不了 不能执行解引用运算!!!!!
// 使用 for
fot ( int * begin = arr ; begin != end ; ++ begin )
cout << * begin << endl ; //输出每一个元素
// 使用 while
while ( begin < end ){ //指针指向相关的对象 可以比较大小(单位(间隔)一样大)
cout << * begin << endl ; //输出每一个元素
++ begin ;
}
//标准库函数 begin() end() 函数得到指针
int iarr = { 0 , 1 , 2 , 3 , 4 }; //函数5个元素
int * beg = begin ( iarr ); //首元素指针
int * end = end ( iarr ); //尾后指针 不能执行解引用运算!!!!!
while ( beg != end && * beg >= 0 ) ++ beg ; //找第一个负值元素
constexpr size_t row = 3 , col = 4 ;
int iarr [ row ][ col ]; //定义未初始化
//下标运算符(size_t 类型) for 循环初始化
for ( size_t i = 0 ; i != row ; ++ i ){
for ( size_t j = 0 ; j != col ; ++ j ){
iarr [ i ][ j ] = i * col + j ; //元素索引为其 值
cout << iarr [ i ][ j ] << ' ' ; // 访问输出 数组元素
}
cout << endl ;
}
// 范围for 初始化
size_t cnt = 0 ;
for (auto & row1 : iarr ) //每一行 引用 int (&row1)[4] 是引用 引用一个含有4个整数的数组
{
for (auto & col1 : row1 ){ // int &col1 每一行的每一个元素 引用 可以读写 除去最内层外 其它必须使用 引用
col1 = cnt ; //赋值
cout << col1 << ' ' ; // 访问 输出数组元素
++ cnt ;
}
cout << endl ;
}
// 指针访问
int ( * p )[ 4 ] = iarr ; //p 指向一个含有4个整数的数组 iarr的 第一行 圆括号必不可少
p = & iarr [ 2 ]; // iarr的 第3行
// for 循环访问
for ( auto p = ia ; p != ia + row ; ++ p ){ // 相当于定义 int (*p)[4] = iarr; p 指向 含有4个整数的数组
for ( auto q = * p ; q != * p + col ; ++ q )
// *p 为含有4个元素的数组 q指向数组的首元素,即指向一个整数 int *q = *p
cout << * q << ' ' ;
cout << endl ;
}
// 使用 标准库函数 begin() 和 end()
for ( auto p = begin ( ia ); p != end ( ia ); ++ p ){
// 相当于定义 int (*p)[4] = iarr; p 指向 含有4个整数的数组
for ( auto q = begin ( * p ); q != end ( * p ); ++ q )
// *p 为含有4个元素的数组 q指向数组的首元素,即指向一个整数 int *q = *p
cout << * q << ' ' ;
cout << endl ;
}
// 使用类型别名
using int_arr_tpye = int [ 4 ]; // int_arr_tpye为包含4个元素的整形数组
typedef int int_arr_tpye [ 4 ]; // 效果同上
for ( int_arr_tpye * p = ia ; p != ia + row ; ++ p ){ // 相当于定义 int (*p)[4] = iarr; p 指向 含有4个整数的数组
for ( int * q = * p ; q != * p + col ; ++ q ) // *p 为含有4个元素的数组 q指向数组的首元素,即指向一个整数
cout << * q << ' ' ;
cout << endl ;
}
Incluye: tipo de retorno nombre de función (lista de parámetros formales) cuerpo de la función El tipo de retorno de una función no puede ser una matriz o un tipo de función, pero puede ser un puntero a una matriz o un tipo de función.
int fact ( int val ){
int ret = 1 ;
while ( val > 1 ) ret *= val -- ;
return ret ; // 返回主调函数 结束函数调用
}
int main (){
int j = fact ( 5 ); // 实参5 初始化 形参(int val)
cout << "5! = " << j << endl ;
return 0 ;
}
Los parámetros formales y las variables definidas en el cuerpo de la función se denominan colectivamente variables locales, que solo son visibles dentro del alcance de la función. Los objetos automáticos locales solo existen durante la ejecución del cuerpo de la función, mientras que los objetos estáticos locales pueden existir después de que se llama a la función. .
// 定义
int count_call ( void ){
int c = 0 ; //局部自动对象 每一次调用都初始化为 0
static int sc = 0 ; //局部静态变量 第一次调用初始化为0 以后每次调用在前一次值上 +1
cout << ++ sc << " " << ++ c << endl ;
}
// 调用
int main (){
for ( int i = 0 ; i < 10 ; ++ i ) count_call (); //sc 输出 1 2,...10,c 输出一直是1
return 0 ;
}
// 源文件 fact.cc
#include "fact.h"
int fact ( int val ){
int ret = 1 ;
while ( val > 1 ) ret *= val -- ;
return ret ; // 返回主调函数 结束函数调用
}
// 函数声明头文件 fact.h
#ifndef FACT_H
#define FACT_H
int fact ( int val ); // 函数声明
#endif
// 主函数调用 fact_main.c
#include <iostream>
#include "fact.h"
using namespace std ;
int main (){
int j = fact ( 5 ); // 实参5 初始化 形参(int val)
cout << "5! = " << j << endl ;
return 0 ;
}
// 编译
gcc fact_main . c fact . cc - o main
Cuando el parámetro formal es un tipo de referencia, se pasa por referencia. Lo que realmente se pasa es el alias del parámetro real y no se realiza ninguna copia. Cuando el valor del parámetro real se copia al parámetro formal, el parámetro formal. y el parámetro real son dos objetos independientes.
int n = 0 ;
int i = n ; // n拷贝给i
i = 42 ; //i的值改变, n的值不变 函数对形参做的所有操作 都不会影响实参 例如 fact(i) 不会改变i的值
int n = 0 ;
int & r_i = n ; //r_i 是 n 的引用 即别名 同一个变量
r_i = 42 ; //r_i 和 n 都变成 42
int n = 0 , i = 42 ;
int * p_n = & n , * p_i = & i ; // 指针
* p_n = 100 ; // n 的值 变为100 指针p_n(变量你存储的地址) 不变
p_n = p_i ; // 现在 p_n 和 p_i 都指向了 i
// 指针形参 函数
void reset ( int * pi ){
* ip = 0 ; //改变了指针 pi 所指向的对象的值
ip = 0 ; // 值改变了 形参ip的值 实参未被改变
}
// 调用
int i = 42 ;
cout << "address of i =" << & i << endl ;
reset ( & i ); // i 的值改变为0
cout << "i = " << i << endl ; // i 的值改变为0
cout << "address of i =" << & i << endl ; // i 的存储地址未改变
// C 程序中 通常使用 指针类型的形参 来访问和改变 函数外部的对象
// C++ 程序中,建议使用引用类型的形参代替 指针形参,这样会更安全,也省时间(引用 无拷贝操作)
// 使用 引用避免拷贝 拷贝大的类对象或容器 都比较低效 费时
void reset ( int & i ){
i = 0 ; // 改变了i所引用的对象
}
// 调用
int j = 42 ;
reset ( j ); // 采样传 引用方式,它的值被改变 调用时 形参i 只是 实参j的一个别名,在函数reset内部对i的操作,即对j的使用
cout << "j = " << j << endl ;
// 比较两个字符串的长度
bool isShorter ( const string & rs1 , const string & rs2 ){
return rs1 . size () < rs2 . size ();
}
// 函数返回多个值 返回字符在某个字符串中第一次出现的位置,并返回出现的 总次数
string :: size_type find_char ( const string & crs , char c , string :: size_type & occurs ){
// 字符串 查找的字符 出现的次数
auto ret = crs . size (); //初始化 第一次出现的位置
occurs = 0 ; //初始化 出现的次数
for ( decltype ( ret ) i = 0 ; i != crs . size (); ++ i ){
if ( crs [ i ] == c ){ // 出现字符 c
if ( ret == crs . size ()) //位置 还未改变 为 第一次出现
ret = i ; //记录第一次出现的位置
++ occurs ; //出现次数 +1 通过形参引用间接返回 出现的次数
}
}
return ret ; //返回第一次出现的位置
}
// 调用
string s ( "some string" );
string:: size_type count = 0 ;
auto index = find_char ( s , 'o' , count );
// 判断 string对象是否是 一个句子
bool is_sentence ( const string & crs ){
// 如果 find_char() 的string参数 必须为 string & 那么不能直接把 const string & 带入
// 需要再定义一个 string对象, 另其为 crs 的副本,再带入
string:: size_type count = 0 ;
return ( find_char ( crs , '.' , count ) == ( crs . size () - 1 )) && count == 1 ;
}
1 不允许拷贝数组
2 在使用数组时会将其转换成指针(指向数组首元素的指针)
// 三个函数等价 形参 都是 const int * 类型
void print ( const int * );
void print ( const int []);
void print ( const int [ 10 ]); // 这里的维度表示期望数组含有多少元素,实际不一定
//调用
int i = 0 ;
j [ 2 ] = { 0 , 1 };
print ( & i ); //&i 是int *类型 可以赋值给 const int *类型
print ( j ); //j 为 &j[0] 是 int * 类型
// C风格字符串 带有一个空字符
void print ( const char * cp ){
if ( cp ) // 确定 cp 不是一个空指针
while ( * cp ) // 只要 指针所指的字符不是 空字符
cout << * cp ++ ; // 打印 字符
}
void print ( const int * beg , const int * end ){
while ( beg != end )
cout << * beg ++ << endl ; //输出当前元素 并将指针向前移动一个位置
}
// 调用
int j [ 2 ] = { 0 , 1 };
print ( begin ( j ), end ( j )); // 使用标准库 begin() 和 end() 函数
void print ( const int ia [], size_t size ){
for ( size_t i = 0 ; i != size ; ++ i )
cout << ia [ i ] << endl ; // 等价于 cout << *(ia+i) << endl;
}
// 调用
int j [ 2 ] = { 0 , 1 };
print ( j , end ( j ) - begin ( j ) ); // 使用标准库 begin() 和 end() 函数 做差来得到数组的大小
void print ( int ( & r_arr )[ 10 ]){ // 注意形式 int (&r_arr)[10] 而 int &arr[10] 成了 包含引用的数组(还不存在,引用不是对象)
for (auto elem : r_arr ) // 变量数组每个元素 范围for
cout << elem << endl ;
}
// 调用 调用时 必须是 大小为10的整形 数组作为实参才可以
int k [ 10 ] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }
print ( k ); // 大小必须为10 多一点 少一点 都不行
void print ( int ( * p_arr )[ 10 ], int rowSize ){} // 形参是 指向 一个含有10个整数的指针
// argc:argument counter 参数计数,argv:argument vector 参数 字符串 容器
int main ( int argc , char * argv []){}
int main ( int argc , char * * argv ){} //第二个参数为 字符串数组 即数组的数组 指针的指针 argv 指向 char*
//程序执行 program -d -o outfile data0
则 argc = 5
argv [ 0 ] = "program" ; // 程序名
argv [ 1 ] = "-d" ; // 第一个参数 开始
argv [ 2 ] = "-o" ; // 第二个参数
argv [ 3 ] = "outfile" ; // 第三个参数
argv [ 4 ] = "data0" ; // 第四个参数 最后一个指针
argv [ 5 ] = 0 ; // 最后一个指针之后 的元素为0
// initializer_list 提供的操作
initializer_list < T > lst ; // 默认初始化 T类型元素的空列表 模实际需要指定模板T的 具体类型
initializer_list < T > lst { a , b , c ...}; // 列表中的元素是 const 常量
lst2 ( lst ); // 拷贝一个initializer_list对象,不会新建,原始列表 和 副本 共享元素
lst2 = lst ; // 同上
lst . size (); // 列表 中的元素
lst . begin (); //返回指向lst中首元素的指针
lst . end (); //返回指向lst中尾元素下一个位置的指针
// 因为有 begin() 和 end()对象可以使用 范围for 遍历参数
// 具体
initializer_list < string > ls ; //initializer_list 的元素类型是 string
initializer_list < int > li ; //initializer_list 的元素类型是 int
// 和vector不同的是 initializer_list中的元素是常量 不能被修改
// 定义函数
void error_msg ( initializer_list < string > ls ){
for (auto beg = ls . begin (); beg != ls . end (); ++ beg )
cout << * beg << " " ;
cout << endl ;
}
//调用函数
//expected 和 actual 是string 对象
if ( expected != actual )
error_msg ({ "function" , expected , actual });
else
error_msg ({ "function" , "okey" });
// 传递了一个含有不同数量元素的 initializer_list
// 定义函数 包含 ErrCode
void error_msg ( ErrCode e , initializer_list < string > ls ){
cout << e . msg () << ": "
for ( const auto & elem : ls ) //范围for 遍历
cout << elem << " " ;
cout << endl ;
}
void foo ( param_list , ...) //
void foo ( param_list ...) //
void foo (...) //
// 交换两个值的函数
void swap ( int & r_i1 , int & r_i2 ){
if ( r_i1 == r_i2 ) // 两个值相等 无需交换
return ;
// 若 执行 到这里,说明还需要继续完成下面的功能
int temp = r_i1 ; //
r_i1 = r_i2 ;
r_i2 = temp ;
// 此处 无需 显示的 return 语句 会隐式指向 return
}
// 两个 string 对象是否 最短的部分 是相同的
bool str_subrange ( const string & str1 , const string & str2 ){
if ( str1 . size () == str . size ())
return str1 == str2 ; // 之间判断 相同长度间的部分是否相同
auto size = ( str1 . size () < str2 . size ()) ? str1 . size () : str2 . size (); //得到最短 字符串的 长度
for ( decltype ( size ) i = 0 ; i != size ; ++ i ){
if ( str1 [ i ] != str2 [ i ]) // 如果 有 不相等的 字符 返回 false
return false; // 有 不相等的 字符 返回 false
}
return true; // 否者 相等 返回 true
}
// 不要 返回 函数内部 临时变量的 引用
string temp ( "glo" );
const string & mainip () {
string ret ( "Empty" ); // 函数内部临时变量
return ret ; // 错误 ,不能返回 临时变量 作为 函数返回值的 引用
// return temp;// 返回 一个调用函数之前就出现的 变量 的引用 或者 参数 为引用类型的参数也可以
}
// 返回 两个字符串中 短的那个
const string & shortString ( const string & s1 , const string & s2 ){ // 返回 s1 或者 s2的引用
return s1 . size () < s2 . size () ? s1 : s2 ; //返回 两个字符串中 短的那个
}
// 函数返回类型 为 标准库 类类型 可以直接调用 其成员函数
auto sz = shortString ( s1 , s2 ). size () // 得到最短字符串 的长度
// 返回 非常量的引用 可以作为 左值 被赋值
char & get_char ( string & str , string :: size_type id ){
return str [ id ]; // 获取指定位置的 字符
}
// 调用
string s ( "a value" );
cout << s << endl ; // a value
get_char ( s , 0 ) = 'A' ; // 将s第一个位置上的字符 替换为 大写的 A
cout << s << endl ; // A value
// 而返回为 常量引用 的不能被赋值
shortString ( "hi" , "bye" ) = "X" ; // 错误 函数返回值是个 常量引用 不能被赋值
vector < string > process (){
if ( expected . empty ())
return {}; // 返回一个 空vector对象
else if ( expected == actual )
return { "function" , "okey" };
else
return { "function" , expected , actual };
}
// 计算阶乘的函数
int factorial ( int val ){
if ( val > 1 )
return val * factorial ( val - 1 );
else
return 1 ;
}
// 递归 返回一个vector的元素函数
void print_vec ( vector < int > vi ){
auto it = vi . begin ();
if ( vi . size () > 1 )
{
cout << * it << endl ;
vi . erase ( it );
print_vec ( vi );
}
else
cout << * it << endl ;
}
// 使用类别别名
typedef int arrT [ 10 ]; // arrT是一个类别别名 表示一个 含有 10个整数 的 数组
using arrT = int [ 10 ]; // 同上
arrT * func ( int i ); // 函数func 返回一个 指向 10个整数的数组的 指针
//直接声明
int arr [ 10 ]; //arr 是一个 含有 10个整数的数组
int * arr_p [ 10 ]; //arr_p 是一个数组 含有 10个指整形针 的 数组
int ( * p2 )[ 10 ] = & arr ; // p2 是一个指针, 指向一个含有 10个整数的 数组 arr
// 函数声明 类似
Type ( * function_name ( parameter_list ))[ dimension ]
int ( * func ( int i ) )[ 10 ]; // 声明一个函数 其形参为 int i ,返回类型 为 指针 ,指向 一个 含有 10个整数的 数组
// 函数指针数组
多个函数可以像数组一样被调用
int ( * fun_p_a [])( char * tmp ); //函数指针数组
// 使用 auto 和 尾置返回类型
auto func ( int i ) -> int ( * )[ 10 ]; // 声明一个函数 其形参为 int i ,返回类型 为 指针 ,指向 一个 含有 10个整数的 数组
// 使用 decltype 知道返回数组 类似类别别名 声明 定义
int odd [] = { 1 , 3 , 5 , 7 , 9 };
int even [] = { 0 , 2 , 4 , 6 , 8 };
decltype ( odd ) * arrPtr ( int i ){ //使用decltype(odd) 表面类型与 odd类似
return ( i % 2 ) ? & odd : & even ; // 返回一个指向数组的指针
}
// 声明一个 返回 引用 一个 含有10个string对象的数组 的函数
string ( & func_r ( string str ) )[ 10 ]; // 直接声明
// 使用类别别名
typedef string arrS [ 10 ]; // 类别别 含有10个string对象的数组
using arrS = string [ 10 ]; // 同上
arrS & func ( string str ); // 函数func 返回一个 指向 10个整数的数组的 指针
// 使用 auto 和 尾置返回类型
auto func ( string str ) -> string ( & )[ 10 ];
// 使用 decltype 知道返回数组 类似类别别名 声明 定义
string str_arr [] = { "a string" , "two" };
decltype ( str_arr ) & arrPtr ( string str );
// 打印 数组元素的 几个 同名函数
void print ( const char * cp ); //出入参数为 带有结束符的