做网站上数字快速增加,17做网站 一件代发,网站开发研究方法,宝安led行业网站建设前言#xff1a; c基础语法#xff08;下#xff09; 文章目录 五、引用5.1 引用概念5.2 引用使用规则5.3 常引用5.4 引用的使用场景5.5 引用和指针的区别 六、内联函数6.1 概念6.2 内联函数的特性 七、auto关键字#xff08;C11#xff09;7.1 概念7.2 使用规则7.3 用于f… 前言 c基础语法下 文章目录 五、引用5.1 引用概念5.2 引用使用规则5.3 常引用5.4 引用的使用场景5.5 引用和指针的区别 六、内联函数6.1 概念6.2 内联函数的特性 七、auto关键字C117.1 概念7.2 使用规则7.3 用于for循环C11 八、指针空值nullptr(C11) 五、引用
5.1 引用概念 引用是C语言中的一种机制用于创建变量的别名。它使用一个已存在的变量来创建另一个名称从而通过不同的名字访问相同的内存位置。 类型 引用变量名(对象名) 引用实体int a 10;
//创建引用
int ra a;5.2 引用使用规则
规则如下 引用必须在声明时进行初始化 引用在定义的同时必须进行初始化。 int a 42;
int a1 a; // 正确引用被初始化创建包含引用的数组 创建一个包含引用的数组。 int array[5] {1, 2, 3, 4, 5};int referencesArray[5] {array[0], array[1], array[2], array[3], array[4]};//referencesArray 中的每个元素都是一个对应于 array 中相应索引位置的引用。上述代码创建了一个引用数组并将每个引用与数组 array 中的元素相绑定。引用不能重新赋值 一旦引用被初始化就不能改变其引用的对象。 int a 10;
int b 20;
int ref a;
ref b; // 此时 a 的值变成 20而不是修改引用的目标一个变量可以有多个引用 多个引用可以同时指向相同的变量这样它们就共享相同的内存地址对该变量的修改将会被所有引用所影响。 int a 10;
int b a;//bc都是a的别名
int c a;int d 5;
b d;//变量a被修改为5同样的b 5c 55.3 常引用 常引用const reference是指在声明引用时使用 const 关键字以表明引用的目标对象在引用生命周期内不可通过别名修改。 #include iostreamint main() {int a 10;const int b a; // 常引用std::cout a: a std::endl;std::cout b: b std::endl;//a:10//b:10// 尝试修改 b 的值这会导致编译错误// b 20;// 修改原始变量 a 的值a 30;std::cout a: a std::endl;std::cout b: b std::endl;//a:30//b:30return 0;
}另外对常量的常引用时合法的但对常量的引用不合法
//可以访问常量的值但不能通过 a 来修改这个值
const int b 10;
//int b 10; 不合法5.4 引用的使用场景 传递函数参数 通过引用传递参数可以避免传递大型对象时的复制开销同时允许在函数内部修改传入的变量。常引用用于确保在函数内部不能修改传入的值。 void modifyValue(int value) {value * 2;
}int main() {int num 5;modifyValue(num);// num 在此处被修改为 10return 0;
}返回引用 函数可以返回引用允许对函数返回值进行修改。这在实现链式调用等情况下很有用。 int array[5] {1, 2, 3, 4, 5};int getElement(int index) {return array[index];
}int main() {getElement(2) 10;// array[2] 在此处被修改为 10return 0;
}这里数组是全局的因此在getElement返回值时数组元素并没有被销毁因此 array[2] 能被成功修改 如果是以下的这种情况变量c 随函数栈帧的销毁也被收回空间那么这个时候返回c的引用就是无效的其返回的值是随机值 int Add(int a, int b){int c a b;return c;
}int main(){int ret Add(1, 2);Add(3, 4);cout Add(1, 2) is : ret endl;return 0;
}5.5 引用和指针的区别 引用概念上定义一个变量的别名指针存储一个变量地址。 引用提供了一种直观的别名机制不需要显式解引用。指针存储变量地址需要通过解引用操作符 * 才能访问目标对象。 引用在定义时必须初始化指针没有要求。 引用在创建时必须初始化并且一旦与某个对象关联就不能再引用其他对象。指针可以在声明后进行初始化也可以在后续重新指向其他对象。 引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何一个同类型实体。 引用在创建后与某个实体绑定无法再引用其他实体。指针可以在运行时指向不同的对象。 没有NULL引用但有NULL指针。 引用不能为NULL必须在初始化时指向一个有效的对象。指针可以为空即指向 nullptr 或 NULL。 在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占4个字节)。 sizeof 运算符对引用返回引用类型的大小。sizeof 运算符对指针返回指针所占的字节大小通常与地址空间的大小相关。 引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小。 引用自增是对引用的实体进行加法操作。指针自增是将指针指向的地址向后移动一个类型的大小。 有多级指针但是没有多级引用。 C 支持多级指针可以有 int**、int*** 等形式。没有多级引用的概念引用通常是单层的。 访问实体方式不同指针需要显式解引用引用编译器自己处理。 引用在使用时无需显式解引用直接使用引用即可。指针需要通过解引用操作符 * 显式访问目标对象。 引用比指针使用起来相对更安全。 引用在使用时更为直观编译器会在一定程度上确保引用的合法性。指针可能引发空指针、野指针等问题需要小心管理。 六、内联函数
6.1 概念 内联函数是C中的一种编译器优化手段它通过将函数的定义嵌入到调用该函数的地方而不是通过传统的函数调用机制以提高程序的执行效率。 使用关键字 inline 来告诉编译器希望将函数内联展开。在函数定义或声明前加上 inline 关键字即可。
inline int add(int a, int b) {return a b;
}int main() {int a 0;int b 1;cout ab add(a, b) endl;return 0;
}6.2 内联函数的特性 适用于短小的函数 内联函数适用于函数体较短小的情况因为内联的目的是减少函数调用的开销而将大型函数内联可能会导致代码膨胀函数被内联展开那么在每个调用点都会生成一份该函数的代码增加代码的体积可能导致更大的可执行文件。 编译器决定内联 使用 inline 关键字只是向编译器发出一个建议最终是否内联取决于编译器的决策。通常编译器会根据函数的复杂性和调用频率等因素来判断是否进行内联。 一般来说将函数规模较小(即函数不是很长具体没有准确的说法取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰 头文件中定义内联函数 通常内联函数的定义会放在头文件中以便在多个源文件中进行内联展开。 // header.h
inline int add(int a, int b) {return a b;
}// main.cpp
#include header.hint main() {int result add(3, 4); // 内联展开return 0;
}七、auto关键字C11
7.1 概念
auto 是C11引入的关键字用于在声明变量时由编译器自动推导变量的类型。使用 auto 可以简化代码特别是在涉及复杂的类型或使用模板时。以下是关于 auto 的一些关键点 自动类型推导 auto 关键字可以用于声明变量让编译器自动推导变量的类型。编译器在编译时会根据变量的初始化表达式推断其类型。 auto x 10; // x 的类型将被推断为 int
auto y 3.14; // y 的类型将被推断为 double
auto z Hello; // z 的类型将被推断为 const char[6]适用于各种类型 auto 可以用于推导各种类型包括基本数据类型、复合类型、指针、引用等。 auto i 42; // int
auto f 3.14f; // float
auto ptr new int(5); // int*
auto ref i; // int7.2 使用规则 auto与指针和引用结合起来使用 用auto声明指针类型时用auto和auto*没有任何区别但用auto声明引用类型时则必须加。 int main(){int x 10;auto a x;auto* b x;auto c x;//用于获取表达式的类型信息cout typeid(a).name() endl;cout typeid(b).name() endl;cout typeid(c).name() endl;*a 20;*b 30;c 40;return 0;
}在同一行定义多个变量 当在同一行声明多个变量时这些变量必须是相同的类型否则编译器将会报错因为编译器实际只对第一个类型进行推导然后用推导出来的类型定义其他变量。 auto a 1, b 2;
auto c 3, d 4.0; // 该行代码会编译失败因为c和d的初始化表达式类型不同不能作为函数的参数类型 函数参数的类型必须在编译时确定而 auto 是用来进行类型推导的无法在函数参数中使用。在函数参数中必须显式指定参数的类型。 void myFunction(auto x) { // 错误auto 不能用作函数参数类型// 函数体
}不能直接用来声明数组 在数组声明中编译器需要知道数组的元素类型和大小而 auto 无法提供这些信息。因此直接使用 auto 来声明数组是不允许的。 auto myArray[] {1, 2, 3}; // 错误auto 不能直接用于数组声明7.3 用于for循环C11
当 auto 用于范围-based for 循环时它会自动推导迭代变量的类型并且可以遍历容器中的元素使代码更加简洁。以下是使用 auto 的范围-based for 循环的示例
auto 自动推导出 num 的类型而 for 循环会遍历 numbers 容器中的每个元素并将元素的值赋给 num。
#include iostream
#include vectorint main() {std::vectorint numbers {1, 2, 3, 4, 5};// 使用 auto 和范围-based for 循环遍历容器中的元素for (auto num : numbers) {std::cout num ;}std::cout std::endl;return 0;
}八、指针空值nullptr(C11) nullptr 是 C11 引入的空指针常量用于代替传统的空指针值 NULL。nullptr 具有更强的类型安全性。 在传统的C头文件(stddef.h)中可以看到如下代码 NULL 实际上是一个宏通常被定义为 0 或 (void*)0。
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif示例
void f(int a){cout f(int) endl;
}void f(int* a){cout f(int*) endl;
}int main(){f(0);f(NULL);f((int*)NULL);f(nullptr);return 0;
}程序本意是想通过f(NULL)调用指针版本的f(int* a)函数但是由于NULL被定义成0因此与程序的 初衷相悖。 在C98中编译器默认情况下将其NULL看成是一个整形常量0。当我们使用NULL调用f(int* a)时必须强转类型 (int*)NULL。而nullptr 明确表示空指针 如果你喜欢这篇文章点赞评论关注⭐️哦 欢迎大家提出疑问以及不同的见解。