做综合医院网站,WordPress分段插件,wordpress破解版,软文写作的技巧说明#xff1a;
面试题来源于网络书籍#xff0c;公司题目以及博主原创或修改#xff08;题目大部分来源于各种公司#xff09;#xff1b;文中很多题目#xff0c;或许大家直接编译器写完#xff0c;1分钟就出结果了。但在这里博主希望每一个题目#xff0c;大家都要…说明
面试题来源于网络书籍公司题目以及博主原创或修改题目大部分来源于各种公司文中很多题目或许大家直接编译器写完1分钟就出结果了。但在这里博主希望每一个题目大家都要经过认真思考答案不重要重要的是通过题目理解所考知识点好应对题目更多的变化博主与大家一起学习一起刷题共同进步写文不易麻烦给个三连
1.指针和引用的差别
答案
定义和声明指针是一个变量它存储了一个内存地址。可以通过使用星号*来声明一个指针变量。引用是一个别名它是已存在的变量的别名通过使用和定义原始变量相同的类型来声明引用。内存操作指针可以通过解引用操作符*来访问和修改指向的内存地址中的值。可以对指针进行算术运算如指针加法和指针减法。引用本身并不直接操作内存地址它只是原始变量的别名对引用的操作实际上是对原始变量的操作。空值指针可以具有空值NULL或nullptr表示指针没有指向任何有效的内存地址。引用必须始终引用一个有效的对象不能为引用赋予空值。重新赋值指针可以被重新赋值可以指向不同的内存地址。引用在声明后不能被重新赋值它始终引用同一个对象。初始化指针可以在声明时不进行初始化也可以在稍后的时间点进行初始化。引用在声明时必须进行初始化并且一旦初始化后就不能再引用其他对象。对象类型指针可以指向任何类型的对象包括基本类型、自定义类型和指针类型。引用只能引用与其声明时相同或兼容的类型的对象。应用区别。总的来说在以下情况下应该使用指针一是考虑到存在不指向任何 对象的可能在这种情况下能够设置指针为空二是需要能够在不同的时刻指向不同的 对象在这种情况下你能改变指针的指向。如果总是指向一个对象并且一旦指向一个对 象后就不会改变指向那么应该使用引用。
2.下面5个函数哪个能够成功进行两个数的交换
#include iostream
using namespace std;void swap1(int p, int q)
{int temp;temp p;p q;q temp;
}void swap2(int *p, int *q)
{int *temp;*temp *p;*p *q;*q *temp;
}void swap3(int *p, int *q)
{int *temp;temp p;p q;q temp;
}void swap4(int *p, int *q)
{int temp;temp *p;*p *q;*q temp;
}void swap5(int p, int q)
{int temp;temp p;p q;q temp;
}int main()
{int a1, b2;// swap1(a,b); // swap2(a, b); // swap3(a, b); // swap4(a, b); // swap5(a,b); cout a b endl;return 0;
}
解析 这道题考察函数参数传递、值传递、指针传递地址传递、引用传递。
swap1传的是值的副本在函数体内被修改了形参p、q实际参数a、b的一个拷贝p、q的值确实交换了但是它们是局部变量不会影响到主函数中的a和b。当函数swap1生命周期结束时p、q所在栈也就被删除了。swap2传的是一个地址进去在函数体内的形参*p、*q是指向实际参数a、b地址的两个 指针。int *temp; *temp *p;是不符合逻辑的一段代码int *temp新建了一个指针但没有分配内存。 * temp * p不是指向而是拷贝。把 * p所指向的内存里的值也就是实参a的值拷贝到 * temp所指向内存里了。但是int *temp不是不分配内存吗的确不分配于是系统在拷贝时临时给了一个随机地址让它存值。分配的随机地址是个“意外”且函数结束后不收回造成内存泄露。那么swap2到底能否实现两数交换吗这要视编译器而定在vscode可以通过测试但是在更加“严格”的编译器如vs2023这段代码会报错。swap3传的是一个地址进去在函数体内的形参*p、*q是指向实际参数a、b地址的两个指针.int *temp; temp p;int * temp新建了一个指针但没有分配内存。tempp是指向而不是拷贝。temp指向了 * p所指向的地址也就是a。函数swap3不能实现两数的交换这是因为函数体内只是指针的变化而对地址中的值却没有改变。函数swap4可以实现两数的交换因为它修改的是指针所指向地址中的值.swap5函数与swap4类似是一个引用传递修改的结果直接影响实参。
答案swap4函数和swap5函数
3.写出下面程序的运行结果
#include iostream
using namespace std;int main()
{int a[3];a[0] 0;a[1] 1;a[2] 2;int *p, *q;p a;q a[2];cout a[q - p] \n;return 0;
}
解析 首先定义了一个整型数组a它有3个元素。然后将数组a的第一个元素赋值为0第二个元素赋值为1第三个元素赋值为2。
接下来定义了两个整型指针变量p和q。将指针变量p指向数组a的首地址即a[0]的位置。将指针变量q指向数组a的第三个元素的地址即a[2]的位置。
然后使用cout语句输出a[q - p]的值。这里的[q - p]表示指针q和指针p之间的偏移量即q指向的元素在数组a中的位置与p指向的元素在数组a中的位置之间的差值。由于q指向a[2]p指向a[0]所以[q - p]的值为2-02。因此输出a[2]的值即2 答案2
4.下列程序的输出结果是什么
#include iostream
using namespace std;class A {
public:int _a;A(){_a 1;}void print(){printf(%d, _a);}
};class B :public A {
public:int _a;B(){_a 2;}
};int main()
{B b;b.print();printf(%d, b._a);return 0;
}
A22 B11 C12 D21
解析 B类中的_a把A类中_a的覆盖掉了。在构造B类时先调用A类的构造函数。所以A类的_a是1而B类的_a是2。 答案C
5.以下描述正确的是
A函数的形参在函数未调用时预分配存储空间 B若函数的定义出现在主函数之前则可以不必再说明 C若一个函数没有return语句则什么值都不返回 D一般来说函数的形参和实参的类型应该一致
解析 A错误的调用到实参才会分配空间。 B函数需要在它被调用之前被声明这个跟main()函数无关。 C错误的在主函数main中可以不写return语句因为编译器会隐式返回0但是在一 般函数中没return语句是不行的。 D正确的。
答案D
6.写出函数指针、函数返回指针、const指针、指向const的指针、指向const的const指针
答案
void (*f)() // 函数指针
void * f() // 函数返回指针
const int * // const指针
int * const // 指向const的指针
const int * const // 指向const的const指针7.下面的数据声明都代表什么 1float(*def)10; 2double(gh)10; 3double(f10)(); 4int((b)10); 5Long ( fun)(int) 6Int ((*F)(int,int))(int) 答案 1float(* * def)10; def是一个二级指针它指向的是一个一维数组的指针数组的元素都是float。 2double*(*gh)10; gh是一个指针它指向一个一维数组数组元素都是double *。 3double(*f10)(); f是一个数组f有10个元素元素都是函数的指针指向的函数类型是没有参数且返回double的函数。 4int * (( * b)10); 就跟“int * (b)10”是一样的是一维数组的指针。 5Long ( fun)(int) 函数指针。 6Int ( * (*F)(int,int))(int) F是一个函数的指针指向的函数的类型是有两个int参数并且返回一个函数指针的函 数返回的函数指针指向有一个int参数且返回int的函数。
8.以下程序的输出是
#include stdio.h
#include iostream
using namespace std;int main()
{int v[2][10] {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}};int (*a)[10] v; // 数组指针cout **a endl;cout **(a1) endl;cout *(*a1) endl;cout *(a[0]1) endl;cout *(a[1]) endl;return 0;
}
解析 本题定义一个指针指向一个10个int元素的数组。a1表明a指针向后移动 1*sizeof(数组大小)a1后共向后移动40个字节。*a1仅针对这一行向后移动4个字节如下 图所示。
答案1 11 2 2 11
9.什么是数组指针指针数组呢
答案 数组指针和指针数组都涉及到指向数组的指针但它们的概念和用法略有不同。 1.数组指针 数组指针是指向数组的指针它可以看作是一个一维数组每个元素是指向数组中元素的指针。例如int (*p)[3]就是一个指向包含3个整数的数组的指针。使用数组指针时可以通过解引用指针来访问数组元素也可以使用指针算术运算来访问数组元素。
示例代码
int arr[2][3] {{1,2,3},{4,5,6}};
int (*p)[3] arr; // p指向arr数组
cout **p endl; // 输出1
cout *(*p 1) endl; // 输出2.指针数组 指针数组是一个数组其中每个元素都是一个指针。例如int *arr[3]就是一个包含3个指向整数的指针的数组。使用指针数组时可以通过下标访问数组元素也可以使用指针解引用来访问指针指向的值。
示例代码
int a 1, b 2, c 3;
int *arr[3] {a, b, c}; // arr数组包含3个指向整数的指针
cout *arr[0] endl; // 输出1
cout *(arr[1] 1) endl; // 错误arr[1]是一个指针不能进行指针算术运算**总结**一句话不够准确来说就是数组指针是指针指向了数组指针数组是数组里面存指针10.写出如下程序片段的输出
#include iostream
using namespace std;int main()
{int a[] {1, 2, 3, 4, 5};int *ptr (int*)(a 1);printf(%d %d, *(a1), *(ptr - 1));return 0;
}
解析 第一个结果好理解是正常的指针运算。 第二个的确是5。首先a表示一个1行5列数组在内存中表示为一个5个元素的序列。int* ptr(int*)(a1)的意思是指向a数组的第6个元素尽管这个元素不存在。那么显然(ptr-1)所指向的数据就是a数组的第5个元素——5。
答案2 5
11.空指针和迷途指针的区别是什么
答案
当delete一个指针的时候实际上仅是让编译器释放内存但指针本身依然存在。这时它就是一个迷途指针。空指针Null Pointer 空指针是指没有指向任何有效对象或函数的指针。在C和C中可以使用特殊的宏常量NULL或者nullptr来表示空指针。空指针是一个有效的指针值但它并不指向任何有效的内存地址。当我们声明一个指针变量但没有给它赋初值时默认情况下它的值是空指针。
通常如果在删除一个指针后又把它删除了一次程序就会变得非常不稳定任何情况都有可能发生。但是如果你只是删除了一个空指针则什么事都不会发生这样做非常安全。 使用迷途指针或空指针如MyPtr0是非法的而且有可能造成程序崩溃。如果指针是空指针尽管同样是崩溃但它同迷途指针造成的崩溃相比是一种可预料的崩溃。这样调试起来会方便得多。
12.C中有了malloc/free为什么还需要new/delete
答案 malloc与free是C/C语言的标准库函数new/delete是C的运算符。它们都可用于申请动态内存和释放内存。然而new和delete提供了更多的功能和便利性优势如下
类型安全性new和delete是类型安全的它们会自动根据指定的类型进行内存分配和释放。在使用new时不需要显式地指定分配的内存大小编译器会根据类型自动计算所需的内存大小。而malloc()需要手动计算所需的内存大小并进行强制类型转换。构造和析构函数的调用new运算符在分配内存后会自动调用对象的构造函数进行初始化。而malloc()只是简单地分配内存空间不会调用构造函数。同样delete运算符在释放内存前会自动调用对象的析构函数进行清理工作。而free()只是简单地释放内存空间不会调用析构函数。重载支持new和delete运算符可以被重载允许用户自定义内存分配和释放的行为。这对于实现自定义的内存管理策略、跟踪内存分配情况等非常有用。对象数组的处理new运算符可以方便地分配对象数组并在释放时自动调用每个对象的析构函数。而malloc()和free()无法正确处理对象数组的构造和析构。
13.说一下C的this指针
答案 1This指针本质是一个函数参数只是编译器隐藏起形式的语法层面上的参数。this只能在成员函数中使用全局函数、静态函数都不能使用this。实际上成员函数默认第一个参数为T* const this。如
class A {
public:int func(int p) { }
};其中func的原型在编译器看来应该是
int func(A* const this, int p);2this在成员函数的开始前构造在成员的结束后清除。这个生命周期同任何一个函数的参数是一样的没有任何区别。当调用一个类的成员函数时编译器将类的指针作为函数的this参数传递进去。如
A a;
a.func(10);此处编译器将会编译成
A::func(a, 10);看起来和静态函数没差别不过区别还是有的。编译器通常会对this指针做一些优化因此this指针的传递效率比较高如VC通常是通过ecx寄存器传递this参数的。 3this指针并不占用对象的空间。 this相当于非静态成员函数的一个隐函的参数不占对象的空间。它跟对象之间没有包含关系只是当前调用函数的对象被它指向而已。 所有成员函数的参数不管是不是隐含的都不会占用对象的空间只会占用参数传递时的栈空间或者直接占用一个寄存器。 4this指针是什么时候创建的 this在成员函数的开始执行前构造在成员的执行结束后清除。 但是如果class或者struct里面没有方法的话它们是没有构造函数的只能当做C的struct使用。采用TYPE xx的方式定义的话在栈里分配内存这时候this指针的值就是这块内存的地址。采用new方式创建对象的话在堆里分配内存new操作符通过eax返回分配的地址然后设置给指针变量。之后去调用构造函数如果有构造函数的话这时将这个内存块的地址传给ecx。 5this指针存放在何处堆、栈、还是其他 this指针会因编译器不同而有不同的放置位置。可能是堆、栈也可能是寄存器。 6this指针是如何传递给类中的函数的绑定还是在函数参数的首参数就是this指针那么this指针又是如何找到“类实例后函数”的 大多数编译器通过ecx寄存器传递this指针。事实上这也是一个潜规则。一般来说不 同编译器都会遵从一致的传参规则否则不同编译器产生的obj就无法匹配了。