C++知识点整理

    xiaoxiao2021-03-25  116

    1:函数中参数缺省问题 函数声明部分:

    void mytest(std::string &hash, float &Deviation, std::vector<std::string> reference=std::vector<std::string> ());

    注意在定义部分是没有给缺省值! 函数定义部分:

    mytest(std::string &hash, float &Deviation, std::vector<std::string> reference) { }

    注意: vector的初始化方式有以下几种,所以初始化的右值可以多种方式:

    vector<string> svec(10); // 10个元素,每个都是空string对象 /vector<string> svec(10, "hi!");

    在函数缺省参数的使用时候上述两种是可用的,而下述两种是不可用的(但是这两种也是vector的初始化方法)。

    ector<string> articles = {"a", "an", "the"}; vector<string> v1{"a", "an", "the"}; // 列表初始化

    2:类中成员不能是该类的对象作为成员 从对象构造函数的角度来说: 因为如果类包含自身类的对象,存在无限初始化的问题。 构造一个类的对象是,先构造成员变量,然后再调用自身的构造函数,如果类包含自身的的对象,那么在调用构造函数之前,需要先构造自身类的对象。而构造自身类的对象时,又得先构造自身的对象,然后调用其构造函数。。。。这样便会无限循环。 从实例化对象分配空间来说: 当用实例化一个类的对象时,编译器会根据类的定义来分配相应的存储空间。也就是说,在创建对象前,一定要有完整的类定义,这样编译器才能正确的计算所需空间。 如果是下面的代码:

    class Screen{ Screen sc; //error, 'sc' uses undefined class 'Screen' //etc... };

    上述代码中,由于Screen还没有定义结束,在内部定义一个Screen类型的对象时,编译器无法知道应该为sc分配多少空间,因此会报注释中的错误。 但是可以,在类定义时,指向自身类型的指针或引用作为数据成员则没有问题。这是因为指针和引用所占存储空间大小与类型无关,所以编译器可以计算分配空间。

    class Screen{ Screen *sc1; //ok Screen &sc2; //ok };

    3:多维数组的访问和赋值问题

    char b[2][3][3]={'1','2','a','b','c','d','e','f','g','h','i','k','L','M','N'}; char (*p)[3][3] = b; char (*r)[3] = b[0]; char *t = b[0][0]; char u = b[0][2][2]; // printf("%x\n",p); std::cout<<*p<<"\t"<<p<<"\t"<<b<<std::endl;//都是数组名 std::cout<<*r<<"\t"<<*t<<std::endl; std::cout<<u<<"\t"<<&u<<std::endl;

    4:检测系统中浮点数0.0的位模式是否与整型数0的位模式相同

    printf("sizeof double is:%d\n",sizeof(double)); printf("sizeof int is:%d\n",sizeof( int )); double d0=0.0; int i0[2]={0,0}; if(*(double*)i0==d0){ puts("is the same!"); } else { puts("not the same!"); }

    从结果看出,是相同的。 5:数组参数的地址和数组参数的第一个元素的地址不同

    void fun1(char ca[]) { printf("char ca:\n"); printf("%x\n", &ca); printf("%x\n", &(ca[0])); printf("%x\n", &(ca[1])); } void fun2(char* pa) { printf("char* pa:\n"); printf("%x\n", &pa);//printf("%#x\n", &pa);打印的方式不同而已,多一个0X printf("%x\n", &(pa[0])); printf("%x\n", &(pa[1])); printf("%x\n", ++pa); } void main() { char test[] = "helloworld"; fun1(test); fun2(test); printf("test:\n"); printf("%x\n", &test); printf("%x\n", &(test[0])); printf("%x\n", &(test[1])); }

    从上述的运行结果,发现数组参数的地址和数组参数的第一个元素的地址不一样,这是为什么呢? 这是因为在fun1()的第二行,打印的内容为”&ca“,而&ca的实际意义为ca的地址,即指向ca的指针。在函数内部,ca本身就是一个指向数组第一个元素的指针,无需取ca的地址,直接打印ca的值即可,取得ca的地址,实际上是该指针的地址。将第二行的语句替换为:printf(“%x\n”, ca)即可。

    6:数组指针和指针数组的区别 1)数组指针(也称行指针) 定义 int (*p)[n]; 括号()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。 如要将二维数组赋给一指针,应这样赋值:

    int a[3][4]={1,2,3,4,5,6,7,8,9,10,11}; int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。 p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] std::cout<<*p<<"\t"<<&a<<"\t"<<p[0][2]<<std::endl; p++;//该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][] std::cout<<*p<<"\t"<<&a<<"\t"<<p[0][2]<<std::endl;

    所以数组指针也称指向一维数组的指针,亦称行指针。

    2)指针数组 定义 int *p[n]; []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]…p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。 如要将二维数组赋给一指针数组:

    int *p[3]; int a[3][4]; for(i=0;i<3;i++) p[i]=a[i];

    这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2] 所以要分别赋值。

    这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。 还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。 比如要表示数组中i行j列一个元素:

    *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

    例如:

    std::cout<<*(p[0]+2)<<"\t"<<*(*(p+0)+2)<<"\t"<<(*(p+0))[2]<<"\t"<<p[0][2]<<std::endl;

    都是输出数字7,都是表示p[0][2] ps: 优先级:()>[]>*

    7:

    8:

    【待补充】

    转载请注明原文地址: https://ju.6miu.com/read-6792.html

    最新回复(0)