C++入门学习

发布时间:2026/6/27 10:17:16

C++入门学习 目录C入门1.namespace命名空间2.C的输入与输出3.缺省参数4.函数重载5.引用5.1引用和指针的关系6.inline函数7.nullptrC入门C兼容C语言的大多数语法在C语言中我们的第一个程序是这样写的#includestdio.h int main() { printf(hello world); return 0; }在C中这样的语法仍然是可以运行的但是在C中我们这样写使用cout进行输出这样写的好处是我们不需要写输出的占位符类型会自动识别类型进行输出所以在自定义类型的输出上会方便很多#includeiostream using namespace std; int main() { cout hello world endl; return 0; }1.namespace命名空间在C中有四个域全局域局部域命名空间域类域命名空间域就是namespace在这里定义的变量以及函数和其他域可以很好地分离开避免命名冲突等问题而在正常情况下编译器查找一个变量时默认只会在局部域和全局域进行查找所以如果要使用命名空间内部的变量我们有三种使用方法指定命名空间访问命名空间::将某个成员展开using 命名空间::变量;展开整个命名空间using namespace 命名空间;第一种方法是最推荐使用的对于命名空间内部的变量以及函数直接指定命名空间去访问例如我们现在将一块空间命名为test在其中定义x以及一个add函数在输出的时候如果没有指定命名空间那么只在全局域以及局部域去查找变量所以第一个x会输出10第二个x因为指定了test这个命名空间那么会输出1add函数因为在命名空间域内所以也需要指定命名空间访问#includeiostream using namespace std; namespace test { int x 1; int add(int x, int y) { return x y; } } int main() { int x 10; cout x endl; cout test::x endl; cout test::add(1, 2) endl; return 0; }2.C的输入与输出C的标准库都放在一个叫做std的命名空间中我们再练习写代码的时候可以直接将std展开这样使用内部函数就很方便头文件iostream定义了标准的输入和输出对象std::cin是istream类的对象主要面向窄字符的标准输入std::cout是ostream类的对象主要面对窄字符的标准输出std::endl相当于一个换行符的作用并刷新缓存区是流插入运算符是流提取运算符使用C在输入输出时会更加方便不需要手动指定输入输出的格式C的输入输出可以自动识别变量类型且更好地支持定义类型对象的输入和输出#includeiostream using namespace std; int main() { int a 0; int b 0; cin a b; cout a b endl; return 0; }3.缺省参数我们在定义函数时可以将某些参数指定一个缺省值表示如果使用函数时没有给该参数手动赋值那么就会调用这个缺省值进行操作缺省分为全缺省和半缺省全缺省就是全部变量都给上缺省值半缺省就是只给一部分变量给缺省值另一部分仍然需要使用函数时手动赋值C规定半缺省的缺省参数必须从右往左依次给不可以跳跃同样的在给实参的时候也必须从左往右给不可以跳跃给实参这样才不会出现歧义不知道哪个实参赋值给了哪个形参例如下面的代码从右往左给了两个形参缺省值在使用函数时从左往右给了三个实参既然有了实参那么变量z就不会使用缺省值10而是使用给的实参3#includeiostream using namespace std; int add(int x, int y, int z 10, int k 20) { return x y z k; } int main() { cout add(1, 2, 3) endl; return 0; }注意一点如果函数的声明和定义是分离的话缺省值只能给在函数声明的位置4.函数重载C允许同一个作用域中出现同名函数只要这些函数的形参不同就可以构成重载不管是参数个数不同还是参数类型不同表现出了多态行为例如以下add函数都构成函数重载在使用时会根据传入参数的类型个数顺序等不同自动调用对应的函数使用起来比较方便int add(int x, int y) { return x y; } double add(double x, double y) { return x y; } int add(int x, int y, int z) { return x y z; } double add(int x, double y) { return x y; }5.引用引用与C语言经常使用的指针的作用基本是一致的引用的写法类型 引用对象例如我们定义一个整型变量b使用c和d引用它相当于给b取了别名在使用c和d的时候本质上就是在使用b这个变量所以直接对c和d修改值可以更改b的值注意一个别名只能引用一个实体变量但是一个变量可以有多个引用所以这里将d赋值为y是将y的值赋值给它而不是d改变了引用对象引用的使用本质是为了简化程序避开复杂的指针因为取别名更容易理解例如张三它的外号叫小张我们说小张在写代码本质上就是张三这个人在写代码直接对我们需要使用的那个变量进行操作比用指针取地址操作更加简便int b 10; int c b; int d b; cout b endl; cout c endl; cout d endl; int y 20; d y;//只能引用一个实体所以这里d依旧是b的别名 //将值更改为20 cout b endl; cout c endl; cout d endl;回想一下之前使用C语言写栈调用初始化函数和入栈函数等操作时我们需要传入栈的地址也就是stack去操作但是如果我们将传入的形参改为引用相当于对这个栈取别名可以直接用这个别名进行操作而且代码可读性更高例如下面这段代码定义了一个叫st的栈然后有三个函数原本我们在函数形参这一块使用的是指针类型的传入然后用指针去操作栈内的变量现在直接使用引用的操作相当于直接对栈本身进行操作函数写起来更简便而且使用函数时很直观的知道是在对栈进行什么操作可以直接传入栈而不是传入一个地址typedef int StackDataTpye; struct StackNode { StackDataTpye* arr; int top;//栈顶 int space;//空间大小 }; typedef struct StackNode SN; void StackInit(SN stack) { //初始化栈 stack.arr (StackDataTpye*)malloc(2 * sizeof(StackDataTpye)); //初始先申请两个空间 if (stack.arr NULL) { perror(malloc); return; } //将栈顶置为0 //空间大小置为2 stack.top 0; stack.space 2; } void StackPush(SN st, StackDataTpye x) { assert(st.arr ! nullptr); if (st.top st.space) { //如果栈顶到达空间上限时 //对数组进行扩容 StackDataTpye* p1 (StackDataTpye*)realloc(st.arr, 2 * (st.space) * sizeof(StackDataTpye)); if (p1 NULL) { perror(realloc); return; } st.arr p1; st.space * 2;//进行二倍扩容 } //进行入栈操作top st.arr[st.top] x; st.top; } void PrintStack(SN st) { //遍历栈进行打印 assert(st.arr ! nullptr); for (int i 0; i st.top; i) { printf(%d , st.arr[i]); } printf(\n); } SN st; StackInit(st); StackPush(st, 1); StackPush(st, 2); StackPush(st, 3); PrintStack(st);注意一下const引用的操作对于一些临时对象和本身就是const修饰的变量的引用需要使用const引用因为引用可以进行权限的缩小但是不可以进行权限的放大例如对于const修饰的变量a用int进行引用是一种权限的放大本来a的值是不允许修改的但是c引用a之后对a的值有修改的风险所以不可以这样写但是权限的缩小是可以的我们可以直接修改bb的值为20注意这里的const作用是防止通过该引用修改bb的值而不是锁定了dd的值为bb修改前的10所以在bb修改为20之后dd的值也是20只不过不能通过直接更改dd的值来修改bb这样写是会报错的看第三个例子yy*3是一个临时对象而C中临时对象具有常性是不可以被修改的所以如果用int直接去引用触发了权限放大所以对x操作时相当于对一个常量进行修改会报错const int a 1; int c a; //这样是会报错的因为const修饰的a值不可更改 //int c是对权限的放大所以不对 //可以进行权限的缩小但是不能进行权限的放大 int bb 10; const int dd bb; //这样进行权限缩小的引用是可以的 bb 20; dd 30; //这样是不能修改的因为dd是const修饰 //所以当bb用别名dd时不能修改 //但是仍然可以通过使用bb变量名修改bb本身的值 int yy10; int xxyy*3; xx; //在C中一个通过表达式产生的值是需要临时拷贝的叫做临时对象 //这个拷贝出来的值具有常性不可以更改 //相当于对于yy*3的拷贝值使用了const修饰 //此时用xx给他取别名没有用const触发了权限放大 //所以会产生报错因为拷贝值具有常性5.1引用和指针的关系引用作为变量的别名不开辟空间指针要存储变量的地址需要开辟一块空间存储引用在定义时必须初始化指针只是建议初始化引用在初始化引用一个对象之后就不能更改了而指针可以不断改变指向的对象引用是直接访问引用的对象而指针解引用之后才是指向的对象引用结果的大小为引用对象的大小指针的大小取决于环境是32位还是64位指针容易出现空指针和野指针的问题引用相对安全一点6.inline函数C设计inline函数的目的就是替代C语言的宏函数因为宏函数在预处理展开替换时会由于优先级的问题导致结果不正确因为宏函数是直接进行替换而且不方便进行调试对于内联函数来说不支持声明与定义分开直接将定义写在需要使用他的文件下因为inline函数使用时是一种替换不会产生链接的操作使用call去开辟函数栈帧所以如果分离声明与定义会由于找不到链接地址而报错inline函数的使用只是对编译器的建议递归函数以及代码量大的函数即使加上inline编译器仍然不会直接展开函数而是call调用代码量小且使用频繁的函数可以用inline函数如果想知道内联函数在运行时是否展开还是直接call调用可通过调试打开反汇编运行到该函数的地方时如果使用call说明没有展开反之则进行了展开例如以下函数虽然是内联函数但是实际使用时还是再用call所以inline对于编译器只是一个建议7.nullptr在C语言中我们用NULL表示指针为空表示无类型指针void*的常量但是在C中NULL可能被定义为常量0所以如果用NULL作为函数实参传入时如果有两个函数一个需要传入一个指针另一个需要传入整型变量但是此时我们用NULL作为实参肯定是希望调用第一个函数但是由于NULL可能被解释为0那么就会调用第二个函数背离了预期所以在C引入了nullptr它是一个特殊关键字可以转换为任意其他类型的指针类型所以使用nullptr就可以避免这种问题因为nullptr只能被隐式转换为指针类型而无法被转换成整数类型

相关新闻