首页 / 资讯中心 / 文章详情

C++设计基础知识点(不包含面向对象)

C++设计基础知识点(不包含面向对象) ★ FEATURED ARTICLE
C基础设计一、基础程序设计结构以.cpp作为文件后缀名的源代码文件#includeiostream//用于输入输出 using namespace std;//可以省略cout,endl等的前缀 int main(){ couttest.cppendl; return 0; }输入cincin 变量;输出coutcout 内容 变量 endl;二、引用​ 引用是 C 独有的语法C 语言没有引用不是新变量只是已有变量的别名语法数据类型 引用名 原变量; //示例 int a 10; int b a; // b 是a的引用别名这里不是取地址符是引用声明标记a和b代表同一块内存空间不是复制一份新数据int a 10; int b a; b 20; cout a; // 输出 20修改ba跟着变引用 b 就是 a 的外号叫 b 和叫 a都是同一个人。使用特点引用必须初始化#include iostream using namespace std; int main() { int a 10; int r1 a; // 定义同时初始化 int r2; // 编译报错引用没有初始化 return 0; }引用的数据类型必须和被引用的变量的数据类型一致int main() { int a 10; double b 3.14; int r1 a; // 类型匹配 int r2 b; // double变量不能用int引用绑定 return 0; }不存在多级引用没有引用的引用int main() { int a 10; int r a; int rr r; // 不是多级引用这里是右值引用C11新语法和本基础章节无关 int rr r; // 编译报错不存在引用的引用多级引用 return 0; }不存在引用类型的数组数组里面存放引用int main() { int a1,b2,c3; int arr1[5] {a,b,c}; int arr2[5] {a,b,c}; // 非法引用数组不能创建 int (ref_arr)[5] arr1; // ref_arr 是整个arr1数组的引用 return 0; }普通引用不能引用常量字面量 / 临时值int main() { int r 100; // 普通引用不能绑定字面常量 const int cr 100; // const常引用可以绑定常量、临时值 return 0; }函数参数值传递​ 实参拷贝一份副本给形参形参是独立的新变量和外面实参互不干扰。 函数内部修改的只是副本不会影响外部原始实参。#include iostream using namespace std; void swap(int x, int y) // x,y 是实参的拷贝副本值传递 { int temp x; x y; y temp; cout 函数内部 x x y y endl; } int main() { int a 10, b 20; swap(a, b); cout 函数外部 a a b b endl; return 0; } /* 函数内部 x20 y10 函数外部 a10 b20 */特点副本独立修改形参外面不变缺点拷贝数据数据量大的时候效率低无法修改外部变量地址传递​ 把实参的地址拷贝给指针形参。 形参指针保存实参内存地址通过解引用*可以直接操作外部原始变量。#include iostream using namespace std; void swap(int *x, int *y) // x,y是指针变量接收实参地址 { int temp *x; *x *y; *y temp; } int main() { int a 10, b 20; swap(a, b); // 调用时要取地址 a b cout a a b b endl; return 0; } //a 20,b 10优点不拷贝原始数据可以修改外部变量缺点:调用时需要手动写取地址函数内部取值需要写*解引用写法麻烦指针存在风险有可能传入空指针nullptr程序崩溃引用传递​ 形参是实参变量的别名形参和实参同一块内存没有拷贝副本。 在函数内部操作形参等价于直接操作外面原始实参。#include iostream using namespace std; void swap(int x, int y) // 表示引用x是main中实参a的别名y是b别名 { int temp x; x y; y temp; } int main() { int a 10, b 20; swap(a, b); // 调用直接写变量名不用写取地址 cout a a b b endl; return 0; } //a 20;b 10优点不需要拷贝副本节省内存效率高传递结构体、大数组优势巨大可以修改外部实参的值和指针效果一样写法简单调用时直接传变量不用函数内不用*解引用不存在空引用比指针更安全底层引用传递编译器底层还是用指针实现但是语法层面简化了。引用 vs 指针特点引用 指针 *本质变量别名语法糖没有独立内存独立变量存地址占用内存初始化定义时必须绑定变量可以先定义后面赋值可空能否改绑一旦绑定不能换目标可以随时修改指向别的变量使用方式直接写名字不用解引用*取值需要解引用*p地址引用和原变量地址完全相同指针变量本身有自己独立地址const 常引用​const关键字修饰引用常引用可以引用常量也可以引用变量如果只读取、不修改实参**推荐使用const 类型 **常引用独有的特性常引用引用变量int var 100; const int ref1 var; cout var var , ref1 ref1 endl; var 200; cout var var , ref1 ref1 endl; // ref1 300; // 错误不能通过常引用修改变量的值常引用引用常量普通引用不能引用常量// int ref2 10; // 错误普通引用不能引用常量 const int ref2 10; // 正确常引用可以引用常量 cout ref2 ref2 endl;常引用可以引用不同类型的变量会进行隐式类型转换生成临时变量double d 3.14; // int ref3 d; // 错误类型不匹配 const int ref3 d; // 正确常引用可以引用不同类型生成临时变量 cout d d , ref3 ref3 endl; d 6.28; cout d d , ref3 ref3 endl; // ref3的值没有改变因为它引用的是临时变量常引用作为函数参数保护实参不被修改同时支持传递常量void printNum(const int num) { cout printNum: num endl; // num 456; // 错误不能修改常引用参数 } int var 100; void printNum(const int num); printNum(123); // 可以传递常量 printNum(var); // 可以传递变量布尔类型常见坑点常引用不能修改引用本身指向的值但原变量可改int a 10; const int r a; a 20; cout r; //输出20 // r 30; // 报错不能通过r修改const 常引用绑定其他类型会产生临时变量断开联动。一旦发生类型转换引用绑定的是临时值不是原变量。区分「const 变量」和「const 引用」const int a 10; const int r a; // 合法常引用绑定const变量 int r2 a; // 普通引用不能绑定const变量a 是只读常量如果允许普通引用int绑定就可以通过引用修改常量语法禁止。三、作用域函数原型作用域​变量的作用域范围在函数原型内即函数声明中变量所在的参数列表内。参数名仅在函数声明的参数列表内有效函数体外部无法访问这些参数名int isEqual(int a, int b); // a, b 的作用域仅限于此声明 // 这里不能访问 a 或 b因为它们属于函数原型作用域 int c a; c b;函数定义时的参数名可以与声明时不同bool isEqual(int x, int y) { // 定义时可以使用不同的参数名 return x y; }局部作用域​变量的作用域范围在函数体内或者在复合语句花括号{}内内层作用域可以访问外层作用域的变量由内向外查找void func() { int localVar 10; // 外层局部变量 cout 外层 localVar localVar endl; { cout 内层 localVar localVar endl; //10 } }外层作用域无法访问内层作用域的变量void func() { { int innerVar 20; // 复合语句内的局部变量 cout 内层 innerVar innerVar endl; } // cout innerVar; // 错误外层无法访问内层变量 }同名变量遵循就近原则内层变量会隐藏外层同名变量void func() { int localVar 10; // 外层局部变量 cout 外层 localVar localVar endl; { int localVar 30; // 内层同名变量隐藏外层变量 cout 内层 localVar localVar endl; // 输出30不是10 } cout 外层 localVar localVar endl;// 输出10 }全局作用域​全局变量从声明处开始到整个程序结束都能访问。所有函数都可以访问全局变量生命周期贯穿整个程序运行期间存储在静态存储区int globalVar 100; // 全局变量整个程序都能访问 void func1() { cout func1: globalVar globalVar endl; } void func2() { cout func2: globalVar globalVar endl; } int main() { cout main: globalVar globalVar endl; func1(); func2(); cout main: globalVar globalVar endl; return 0; }全局变量默认初始化为0int globalVar; // 全局变量整个程序都能访问 void func1() { cout func1: globalVar globalVar endl;//0 } void func2() { globalVar 200; // 修改全局变量 cout func2: globalVar globalVar endl;//200 } int main() { func1(); func2(); return 0; }类作用域​类内部的成员能够访问的区域被称为类作用域类成员成员变量和成员函数的作用域在类内部类外部访问需要通过对象、指针或引用并使用 . 或 - 操作符class MyClass { private: int privateVar 100; // 私有成员类外不可访问 public: int publicVar 200; // 公共成员类内外都可访问 void classFunc() { cout privateVar privateVar endl; cout publicVar publicVar endl; } }; int main() { MyClass obj; obj.classFunc(); // 通过对象调用成员函数 // cout obj.privateVar; // 错误私有成员类外不可访问 cout obj.publicVar obj.publicVar endl; return 0; }类成员函数内部可以直接访问类的所有成员包括private成员类的静态成员属于类作用域不属于对象class MyClass { private: int privateVar 100; // 私有成员类外不可访问 public: int publicVar 200; // 公共成员类内外都可访问 void classFunc() { // 类内部可以直接访问所有成员 cout privateVar privateVar endl; cout publicVar publicVar endl; } };命名空间作用域​在指定的命名空间内进行有效访问的区域。**语法** namespace 命名空间名 { // 变量、函数、类等 }命名空间用于组织代码避免命名冲突namespace MyNamespace { int namespaceVar 200; void namespaceFunc() { cout 命名空间中的函数namespaceVar namespaceVar endl; } class MyClass { public: void classFunc() { cout class endl; } } } int main() { return 0; }命名空间内的成员需要使用 :: 作用域区分符访问namespace MyNamespace { int namespaceVar 200; void namespaceFunc() { cout 命名空间中的函数namespaceVar namespaceVar endl; } } int main() { // 使用作用域区分符访问 cout MyNamespace::namespaceVar MyNamespace::namespaceVar endl; MyNamespace::namespaceFunc(); return 0; }可以使用 using namespace 指令简化访问namespace MyNamespace { int namespaceVar 200; void namespaceFunc() { cout 命名空间中的函数namespaceVar namespaceVar endl; } } int main() { // 使用using指令简化 using namespace MyNamespace; cout 使用using后namespaceVar namespaceVar endl; return 0; }命名空间可以嵌套namespace MyNamespace { // 嵌套命名空间 namespace InnerSpace { int innerVar 300; } } int main() { // 访问嵌套命名空间 cout MyNamespace::InnerSpace::innerVar MyNamespace::InnerSpace::innerVar endl; return 0; }命名空间可以跨文件四、函数的默认参数概念​C程序允许用户给函数预先设置参数的默认值。如果用户不为该函数传递实际参数则函数使用参数的默认值如果用户传递了实际参数则函数使用实际参数。默认参数是在编译阶段确定的编译器会在调用点将缺失的参数替换为默认值。语法// 函数声明时设置默认参数 返回值类型 函数名(数据类型 变量名1值, 数据类型 变量名2值...); //三个参数String类型int类型String类型 void printInfo(string name 张三, int age 18, string gender 男);使用规则声明与定义的关系(如果函数声明处添加了参数默认值则函数定义处可以不加默认值)// 声明时设置默认值 void printInfo(string name 张三, int age 18, string gender 男); // 定义时可以不加默认值 void printInfo(string name, int age, string gender) { cout 姓名: name endl; cout 年龄: age endl; cout 性别: gender endl; } //**注意**如果函数只有定义没有声明则默认参数必须在定义处设置 void printInfo(string name 张三, int age 18, string gender 男) { // 函数体 }默认参数的顺序(在拥有多个参数的函数使用默认值时默认值的右边不能有非默认值存在)// 正确默认值都在右边 void func1(int a, int b 10, int c 20); // 错误默认值右边有非默认值 // void func2(int a 10, int b, int c); // 错误默认值之间有非默认值 // void func3(int a, int b 10, int c, int d 30);引用作为函数参数的默认值(普通引用不能绑定到临时对象因此普通引用参数不能加默认值)//普通引用 int ref 必须绑定到一个左值可修改的变量; //10 是一个右值临时对象无法绑定到普通引用; //const int ref 可以绑定到右值因为它承诺不修改引用的对象 // void func1(int ref 10);// 错误普通引用不能绑定到常量10临时对象 // 正确const引用可以绑定常量 void func2(const int ref 10); // 正确使用指针代替引用 void func3(int *p nullptr); // 正确普通参数可以加默认值 void func4(int num 10);五.内联函数概念​当一个函数在程序中被频繁大量调用时可以将这个函数声明为内联函数Inline Function。**普通函数调用的开销** 1. 主调函数暂停执行 2. CPU切换到被调函数开辟函数栈帧内存 3. 保存当前执行状态现场 4. 重置程序计数器PC跳转到被调函数 5. 执行被调函数 6. 被调函数结束后释放函数栈帧 7. 恢复现场恢复寄存器、程序计数器等 8. 继续执行主调函数 **内联函数的优化** 内联函数在编译之后会将函数体**直接嵌入**到函数调用处消除函数调用的开销提高执行效率。 **形象比喻** - **普通函数**就像打电话需要拨号、等待接通、通话、挂断有很大的开销 - **内联函数**就像面对面交谈直接传递信息几乎没有开销语法inline 返回值类型 函数名(形参列表); inline int add(int a, int b) { //函数体 }语法原则函数的语句小于等于5行函数体过于庞大时内联展开会导致代码体积急剧增加// 不适合内联函数体过大 inline int computeSum(int arr[], int size) { int sum 0; for (int i 0; i size; i) { // 有循环 sum arr[i]; } return sum; }函数内没有循环结构循环会导致代码重复展开增加代码体积// 不适合内联函数体过大 inline int computeSum(int arr[], int size) { int sum 0; for (int i 0; i size; i) { // 有循环 sum arr[i]; } return sum; }函数不能递归递归函数无法在编译时确定展开次数// 不适合内联递归函数 inline int factorial(int n) { if (n 0) return 1; return n * factorial(n - 1); // 递归 }工作原理//普通函数调用 int add(int a, int b) { return a b; } int main() { int x add(3, 5); // 编译后call add return 0; } //内联函数展开 inline int add(int a, int b) { return a b; } int main() { int x add(3, 5); // 编译后int x 3 5; return 0; } //编译器会将 add(3, 5) 直接替换为函数体 3 5从而避免了函数调用的开销。
阅读完成 · 觉得有帮助?
咨询建站