C++基础知识篇(一)——输入输出、命名空间、引用、函数特性

    xiaoxiao2025-06-10  24

    一.输出程序的基本组成

    1.cout 与 cin

    C++编程语言互换中的标准输入流,需要头文件 iostream

    格式:cin >> 变量1 >> 变量2 >> … >> 变量n;

               cout << 变量1 << 变量2 << 变量3 ....;

    #include <iostream> using namespace std;//定义命名空间 int main(void) { int num; cout << "请输入一个整数:" << endl; //endl 相当于换行 cin >> a; return 0; }

    2.命名空间:namepace 

    1>通俗来讲:比如,你是A公司的小张。那么命名空间 A公司,变量名:小张

    2>为什么要使用命名空间?比如:A创建了函数fun() ,同时B也创建了函数fun(),那么主函数中要想访问某个指定的fun(),就需要通过建立命名空间这两个fun()区分开来

    #include <iostream> //包含C语言的stdio.h ,所以说C是C++的一个子集 using namespace std;//C++的所有组件都在名为std的命名空间中 namespace A { int n = 10; void fun() { cout << "A" << endl; } } namespace B { namespace c { int a = 10; } int a = 10; } using namespace B;//说明下命函数当中默认访问B空间里面的内容,则可省略 B:: int main() { cout << A::n << endl; //访问空间A内的变量 A::fun(); //访问空间B内的函数 cout << B::a << endl; return 0; }

    二.C++空间的申请和释放

    1. 在C语言中,动态分配内存用malloc()函数,释放用free()函数。在C++当中,这两个函数仍然可以使用,但是C++又新增了两个关键字,newdelete ; new用来动态分配内存,delete 用来释放内存。

    int *p = new int; //分配1个int型的内存空间 delete p; //释放内存

     如果希望分配一组连续的数据,可以使用new[ ];

    int *p = new int[10]; //分配10个int型内存空间 delete[] p;

    Tips:和malloc一样,new也是在堆区分配内存,必须手动是释放,否则只能等到程序运行结束由操作系统回收。为了避免内存泄露,通常new 和delete、new[ ]和delete[ ]操作符应该成对出现,并且不要和C语言中malloc()、free()一起混用。在C++中建议new和delete来管理内存,他们可以使用C++的一些新特性,最明显是可以自动调用构造函数和析构函数。

    三.引用

    (一)变量的引用

    1.就是某一变量的一个别名,对引用操作与对变量直接操作完全一样

    2.声明方法:类型标识符 &引用名 =  目标变量名

    例如:int  a  =  10;

               int &c = a;

    3.注意:1>引用仅仅是变量的别名,而不是实实在在的定义了一个变量,因此引用本身并不占用内存,而是和目标变量共同指向目标变量的内存地址.

                 2>表达式中的取地址符&不再是取变量的地址,而是用来表示该变量是引用类型的变量。

                 3>定义一个引用时,必须对其初始化。

    #include <iostream> using namespace std; int main() { // a 与 c 关联同一个内存空间 // 引用声明的时候一定要初始化 // 同一个变量可以多个引用(通俗讲就是一块内存空间可以起多个名字) // 定义之后不能指向其他的 int a = 12; int& c = a; // 声明变量a的一个引用c,c是变量a的一个别名 // 如果c 已经是 a的引用了,那么c不能再引用其他的变量 int& d= c; cout << &a << ' ' << &c << ' ' << &d << endl; //内存空间一样 c = 13; cout << "a = " << a << endl; return 0; }

    运行结果可以看出, a、c、d的地址都是一样的,当改变了C的时候,也同时改变了a

    0xbfeede44 0xbfeede44 0xbfeede44 a = 13

    其他类型变量的引用:常量的引用、数组的引用、指针的引用

    //其他类型的引用 #include <iostream> using namespace std; int main() { //常量的引用 const int& a = 12; // 常量的引用且不能修改常量 //数组的引用 //方式: 引用 类型 //类型一定要匹配 int arr[12]; int (&p)[12] = arr; p[2] = 12; cout << arr[2] << endl; //指针的引用 int b = 12; int *point = &b; int* (&p3) = point; *p3 = 34; cout << *point << ' ' << b << endl; return 0; }

    运行结果

    [root@localhost CPP]# ./typedef_1 12 34 34

     (二)引用的应用

    1.引用作为参数

    引用的一个重要作用就是作为函数的参数,以前的C语言中函数参数传递是值传递,如果有大块数据作为参数传递时,采用的方案往往是指针,因为这样就可以避免件整块数据全部压栈,可以提高程序的效率,但是现在C++中有增加了一种同样有效率的选择(在某些特殊情况下又是必须选择),就是引用

    使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参的操作,而使用一般变量传递函数的的参数,当发生函数参数调用时,需要给形参分配存储单元,形参变量是实参的副本;如果传递的是对象,还将调用拷贝构造函数,因此,当参数传递的数据交大时,用引用比用一般变量传递参数的效率和所占空间好

    //引用作参数 #include <iostream> using namespace std; void fun(int& a) // a关联b的空间是同一个,改变a的值不足以改变b的值 { a = 13; //cout << a << endl; } void fun2(int a)// a与b的空间不是一个 { a = 14; cout << a << endl; } void fun3(int *a) { *a = 15; } int main() { int b = 12; fun(b); cout << b << endl;// 引用 fun2(b); // 将b的值传递给了a,相当于a的初始化。但是a与b的地址是不同的,改变a地址里面的值不足以改变b地址里面的值 cout << b << endl;// 不引用 fun3(&b); cout << b << endl;// 将b的地址传递给了形参a return 0; }

    运行结果: 

    [root@localhost CPP]# ./typedef_3 13 14 13 15

     2.引用作为返回值:

    格式:类型标识符  &函数名(形参列表及类型说明)

    #include <iostream> using namespace std; //不要引用局部变量 int& fun() //类型 { int a = 12; return a; } int main() { int& b = fun(); //当这条语句结束之后,内存空间以及被释放了 cout << b << endl; //那么就操作了非法空间 return 0; }

    注意点:1>不能返回局部变量的引用

                   2>不能返回函数内部new分配的内存的引用

                   3>可以返回类成员的引用,但是最好是const

                   4>引用与一些操作符的重载:流操作符<<和>>,这两个操作符常常希望被连续使用

    3.引用与指针的区别

    1.指针不需要初始化而引用一定需要初始化

    2.引用初始化之后就不能再去引用其他的,而指针可以

    3.引用不占空间而指针占空间

    4.引用是对空间的直接操作,指针是间接操作(通过指针操作符)

    5.引用更安全,引用之后无法偏移,指针是可以偏移的

    四.C++函数特性

     (一)函数参数缺省值

    #include <iostream> using namespace std; void fun(int a = 12,char c = 'c') //全部指定 { cout << a << ' ' << c << endl; } void fun1(int a,char c = 'c',float d = 12.22) //部分指定,从右向左连续指定 { cout << a << ' ' << c << ' ' << d << endl; } int main() { //函数调用,有默认值的参数,可以不用创建实参 fun(); //没指定默认值的,一定要传递实参 fun1(123); //有默认值,还传实参,实参会覆盖掉默认值 fun1(124,'d'); return 0; }

    运行结果:

    [root@localhost CPP]# ./quesheng_17 12 c 123 c 12.22 124 d 12.22

    (二)函数重载

    在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 int、float、char、bool 等,我们需要通过参数把变量的地址传入函数内部。在C语言中,程序员往往需要分别设计出三个不同名的函数,其函数原型与下面类似

    void swap1(int *a, int *b);      //交换 int 变量的值

    void swap2(float *a, float *b);  //交换 float 变量的值

    void swap3(char *a, char *b);    //交换 char 变量的值

    void swap4(bool *a, bool *b);    //交换 bool 变量的值

    但在C++中,这完全没有必要。C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading)。借助重载,一个函数名可以有多种用途。 参数列表又叫参数签名,包括参数的类型、参数的个数和参数的顺序,只要有一个不同就叫做参数列表不同

    #include <iostream> using namespace std; void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void swap(float *a, float *b) { float temp = *a; *a = *b; *b = temp; } int main() { int n1 = 100, n2 = 200; swap(&n1, &n2); cout<<n1<<", "<<n2<<endl; float f1 = 12.5, f2 = 56.93; swap(&f1, &f2); cout<<f1<<", "<<f2<<endl; return 0; }

    函数重载的规则:

    函数名称必须相同参数列表必须不同(个数不同、类型不同、参数排列顺序不同)函数的返回类型可以相同也可以不相同!!!仅仅返回类型不同不足以成为函数的重载

    (三)内联函数

    作用:inline 和 宏定义#define的作用基本类似,都是替换或者展开。 在程序编译阶段,如果遇到内联函数,则将内联函数的实现在当前位置展开。内联的目的是为了减少函数的调用开销,从而提高运行效率,但会增加代码体量。

    指定内联函数的方法很简单,只需要在函数定义处增加 inline 关键字。

    #include <iostream> using namespace std; //内联函数,交换两个数的值 inline void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int main() { int m, n; cin>>m>>n; cout<<m<<", "<<n<<endl; swap(&m, &n); cout<<m<<", "<<n<<endl; return 0; }

    注意:要在函数定义处添加 inline 关键字,在函数声明处添加 inline 关键字虽然没有错,但这种做法是无效的,编译器会忽略函数声明处的 inline 关键字。

     使用内联函数的缺点也是非常明显的,编译后的程序会存在多份相同的函数拷贝,如果被声明为内联函数的函数体非常大,那么编译后的程序体积也将会变得很大,所以再次强调,一般只将那些短小的、频繁调用的函数声明为内联函数。

     

     

     

     

     

     

     

     

    最新回复(0)