C++入门的基本操作

本文详细介绍了C++中的命名空间,包括其定义、作用和使用方法。接着讲解了C++的输入输出机制,与C语言的区别,并举例说明。此外,还阐述了缺省参数的概念、分类和注意事项,以及函数重载的条件和应用场景。最后,文章提到了引用的特性和引用与指针的区别,并简单提及内联函数在提升程序效率中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.命名空间

在c/c++中,变量、函数和后面要学的类都是大量的存在,这些变量、函数和类的名称将都存在于全局作用域中,可能会会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是为了针对这种问题。

而定义一个命名空间需要用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

看下面的例子:

//1.常见的命名空间
namespace N1
{
//命名空间中的内容是可以定义变量也可以定义函数
    int Add(int a, int b)
    {
        return a+b;
    }
    int a;
    int b;
}

//2.命名空间还可以进行嵌套
namespace N2
{
    int a;
    int Sub(int c, int d)
    {
        return c-d; 
    }
    namespace()
    {
        int Mul(int c, int d)
        {
            return c*d;
        }
        int c;
        int d;
    }
}
//3. 也可以出现空间名字相同的命名空间
//那么如果一个工程出现多个相同名称的命名空间时是如何处理的?
//其实如果一个工程中出现多个相同名称的命名空间时,编译器最后会合成同一个命名空间
namespace N1
{
    int Sub(int a, int b)
    {
        return a-b;
    }
    int c;
    int d;
}

需要注意的是:一个命名空间定义了一个新的作用域,命名空间中所有内容都局限于这个命名空间中。

上面我们定义了几个命名空间,那么我们如何使用这些命名空间中的成员(变量和函数……)呢?

下面我们来看三种命名空间的使用例子:

1.在你使用的成员前面加命名空间的名称和作用限定符:

int main()
{
    //printf("%d\n", a);          //这样写是错误的,因为命名空间的成员的变量局限于命名空间内
    printf("%d\n", N1::a);        //这是访问一个普通的命名空间成员的方式
    printf("%d\n", N2::N3::a);    //这是访问嵌套命名空间中里面的命名空间的成员的访问
    return 0;
}

2.使用using将命名空间中成员的引入(这种做法相当于将这个成员的作用域,变成一个全局作用域,那么如果此时出现一个和这个成员名字相同的全局变量时,这时就不能再这样写了,这时只要在变量的前面加一个命名空间的名字和作用域限定符(::)即可);

using N1::b;

//int b;
int main
{
    //printf("%d\n", N1::b); 
    printf("%d\n", b);//这时候变量的前面不用加任何的东西
    return 0;
}

3.使用using namespace命名空间名称的引入(这样的作法相当于直接将命名空间的内容导入文件中,相当于全局变量和函数来使用),(同样如果由变量的名字发生冲突时,在变量的前面加命名空间的名字和作用域限定符)

using namespace N1;
int main()
{
    printf("%d\n", a);
    Add(10,20);
    return 0;
}

以上就是命名空间的定义和用法

2.C++中的输入和输出

接下来分析c++的输入和输出与c语言有什么不同?

首先看下面的一个例子:

#include<iostream>
using namespace std;

int main()
{
    int i = 0;
    cin>>i;
    cout<<"hello Word"<<endl;
    return 0;
}

1.首先头文件的引用,有的书上iostream后面是有.h的,但是现在基本不加.h,这是为了区分C++和C语言的不同

2.其次为什么要有using namespace std这句话呢?因为C++把标准库存在了标准的命名空间中,而这个命名空间的名字就是std,这步的操作就是将命名空间std中的标准库导入文件中。

3.cout是标准输出,cin是标准的输入,使用这两个来输入和输出更加的方便,因为以前C语言中输出一个变量时都要前面指明变量的数据格式,但是cout不用指出数据的格式。<< 运算符被重载来输出内置类型(整型、浮点型、double 型、字符串和指针)的数据项。endl 用于在行末添加一个换行符。

注意:早期标准库将所有的功能都在全局域中实现,声明在.h后缀的头文件中,使用时只要包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确的使用命名空间,规定C++头文件不带.h;旧的编译器(vc)中还支持<iostream.h>的格式,但是后续的编译器已经不支持,因此推荐使用<iostream>+std的方式。

3.缺省参数

1.概念:缺省参数是声明和定义函数时为函数的参数指定一个默认值。再调用该函数时,如果没有指定的实参则采用该默认值,否则使用指定的实参。

如下所示:

void TestFunc(int a = 0)
{
    cout<<a<<end1;
}


int main()
{
    TestFunc();    //不给函数传参,此时函数使用的是参数的默认值
    TestFunc(10);    //此时给函数传参,那么函数使用的是传过去的值。
    return 0;
}

2.缺省的参数分类

             1.全缺省参数(将函数的所有的形参都给一个默认值)

             2.半缺省参数(没有将所有的的形参都给默认值)

注意:(1)半缺省的参数必须从右向左依此给出,不能间隔给出。

                         原因:函数的调用约定(-cdel)规定函数传参从右向左。

          (2) 缺省的参数不能在函数声明和定义中同时出现。

                        原因:如果声明和定义的时候所给形参的缺省值不相同的话,那么如果你不给函数传参的时候,编译器就无法识别到底要使用哪一个缺省值。

         (3)缺省值必须是常量或全局变量

         (4) C语言不支持

4.函数重载

函数重载是函数的一种特殊的情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参链表(参数的个数或类型或顺序)必须不同,常用来处理实现功能类似的数据类型不同的问题。

如下图所示:

int Add(int a, int b)
{
    return a+b;
}
double Add(double a, double b)
{
    return a+b;
}
long Add(long a, long b)
{
    return a+b;
}
int main()
{
    Add(10,20);
    Add(10.0, 20.0);
    Add(10L,  20L);
    return 0;
}

注意:(1)如果两个函数仅仅是函数的返回值不同的话,不会形成函数的重载。

           (2)最好不要将一个无形参的函数和一个全缺省函数形成缺省,不然的话会发生问题。

                     原因如下:

int   Add()
{
    return 1;
}

int Add(int a = 1, int b = 2)
{
    return a+b;
}


int main()
{
    Add();    //这个时候如果调用Add函数且不给函数传参时,编译器就不知道调用哪个函数
    return 0;
}

6.引用

引用不是定义一个变量,而是给已存在的变量取了一个别名,而且编译器不会为引用的变量开辟一块空间,它和它引用的变量共同使用一块空间。

如下图所示:

void  TestRef()
{
    int a = 10;
    int & ra = a;     //这就是引用

    printf("%d", &a);
    printf("%d", &ra);   //这两个的地址是相同的。
    return 0;
}

但是引用和引用的实体必须是同一个类型的。

         原因如下

double a = 1.34;
int & ra =  a;    //这种写法是错误的
const int & ra = a;    //这种写法可以,但是输出的ra只有a的整数部分。

     因为引用和变量的类型是不同的,所以编译器会开辟一块临时的空间来存放int类型的数据,然后将a的整数部分放如临时空间中,但是由于编译器临时开辟的空间的名字和地址我们都不知道,所以这个临时空间不能改变(也就是这块临时的空间具有常性)所以加const以后会通过编译。5.

引用需要注意以下几个特性:

              1.引用在定义的时候必须要初始化。

              2.一个变量可以有多个引用

              3.引用一旦引用一个实体,再不能引用其他实体。

int main()
{
	int a = 0;
	//int &ra;    //这样写是会出现错误的
	int &ra = a;
	int &rra = a;
	printf("%p, %p, %p", &a,&ra,&rra);
	return 0;
}

使用的场景

        1.做参数:

void Swap(int a, int b)  //这样可以直接交换两个变量的数据,并且结果和传变量地址过来的结果是一样的。
{
    int tmp = a;
    a = b;
    b = tmp;
}

      2.也可以用作返回值:

int & Test()
{
    int a = 10;
    return a;
}

但是将引用作为返回值有要注意的地方 你可猜想一下面的代码输出的是什么?

int main()
{
    int & a = Test();
    printf("%d\n", a);
    printf("%d\n", a);
    printf("%d\n", a);
    return 0;
}

为什么是这个结果呢?

这个涉及到了C语言中栈帧的知识,当一个函数调用结束后,空间会被自动释放掉,但是如果你没有做任何操作的话,你任然可以用地址来找到函数中某个变量的值,第一个printf时,存放变量的空间还没有改变,你可以取到正确的值,但是printf执行后可能会修改存放的那片空间,这时第二个printf取值是就无法取到这个变量来的值。第三个也是如此。(这就好比一块写满字的黑板,如果没人修改黑板上的内容的话,你会一直看到原来的内容,但是一旦有人擦掉原来的内容而写上新的东西的话,你看到的就不是原来的内容)。

3.引用和指针的区别

在前面我们说过引用相当于起了一个别名,没有独立的空间,和引用的实体共用同一块空间。

但是从上面的反汇编中可以看出引用在底层实现其实使用空间的,因为引用是按照指针方式来实现。

指针和引用不同:

          1.引用在定义时必须初始化,指针没有要求。

          2.引用在初始化时引用一个实体后,就不能再引用其他的实体,而指针则可以在任何时候指向同类型的另一个实体

                     因为int &ra = a; 相当于int * const ra = &a;

          3.没有NULL引用,但是有NULL的指针

          4.在sizeof中含义不同:引用的结果为引用类型的大小,但指针始终是地址空间所占的个数

          5.引用自加即引用的实体增加1,指针自加是向后便宜一个类型的大小

          6.有多级指针但是没有多级的引用。

          7.访问实体的方式不同,指针需要显示的解引用,引用编译器自己处理。

          8.引用使用起来比指针更加的安全

                         因为指针在函数中需要判空,而引用不需要。

其实引用和指针在传参上的效率几乎相同

5.内联函数

以inline修饰的函数叫做内联函数,编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。

inine是一种以空间换时间的做法,省去调用函数额开销,所以代码很长或者循环/递归的函数不适宜使用内敛函数

inline对于编译器来说只是一个建议,编译器会自动优化,但是如果定义为inline的函数体内有循环或者递归的话,编译器会忽略掉内联,所以函数前加inline该函数并不一定会称为内联函数。

如果你要判断一个函数是否是内联函数的话,在调用的语句中,打开反汇编,如果有call语句调用函数的话,代表不是内联函数,反之是内联函数。

c语言中的有宏,C++有什么技术可以替换宏?

         1.常量定义   换用const来定义,(因为在c++上一个变量前面加const这个变量相当于常量)

         2.函数定义,换用内联函数。 (编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值