指针与引用(面试宝典笔记三)
指针与引用
1:指针和引用的差别
(1)非空区别。即指针可以赋空值,但引用不能。
(2)合法性区别。在使用引用之前不需要测试它的合法性,相反,指针则总是被测试,防止其为空。
(3)可修改区别。引用指向的对象在初始化时确定,以后不可改变; 指针可改变指向。
(4)应用区别。使用指针:a.存在不指向任何对象的情况。b.不同时刻指向不同的对象。
使用引用:总是指向同一对象,并且不需要改变指向。
例题:
1:please check out which of the following statements are wrong?
#include <iostream> using namespace std; int main() { int iv; int iv2 = 1024; int iv3 = 399; int &reiv; int &reiv2 = iv; int &reiv3 = iv; int *pi; *pi = 5; pi = &iv3; const double di; const double maxWage = 10.0; const double minWage = 0.5; const double *pc = &maxWage; cout << pi; return 0; }
错误:7,11,13行。
7:引用必须在声明时同时初始化。
11:pi没有指向,不可以对其赋值。
13: 本地的const常量必须在第一次声明时就初始化。
例题2:
这个程序有什么问题?该如何修改?
char *strA() { char str[] = “Hello World”; return str; }
str[]数组是属于函数strA()的局部变量,当调用完这个函数后,局部变量str被销毁,所以返回的结果是不确定且不安全的。
要获得正确的结果,可做如下修改:
a.
const char* strA() { char *str = “Hello World”; //”Hello World”是字符串常量,它位于静态存储区,在程序的生命期内是恒定不变的。 //str是一个指针变量,它指向这个字符串常量的首地址。 //指针变量str的值是可以改变的(可以改变指向),不能改变的是内存中存储字符串常量的内存单元的值。 return str; }
b.
const char* strA() { static char str[] = “Hello World”; /*静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的 函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。*/ return str; }
C++五大内存分区及区别
字符串常量的生命期与存储域的讨论
静态变量的生存期与作用域
例题3:
What results after run the following code ?
#include <stdio.h> int main() { int *ptr; ptr = (int *)0x8000; *ptr = 123; return 0; }
Answer:
会导致运行时错误。
这种做法给一个指针分配一个随意的地址,相当危险(直接给未作声明的地址赋值编译器会报错的)。
例题4:
下面程序的输出结果时什么?
#include <iostream> #include <cstdio> using namespace std; class A { public: int _a; A() { _a = 1; puts("调用A的构造函数"); } void print() { printf("%d\n", _a); } }; class B : public A { public: int _a; B() { puts("调用B的构造函数"); _a = 2; } }; int main() { B b; b.print(); printf("%d\n", b._a); return 0; }
A. 2 2 B. 1 1 C. 1 2 D. 2 1
Answer:
C
B中的_a把A中的_a覆盖,创建B类的对象时,先调用A类的构造函数,再调用B类的构造函数。
所以创建对象b之后,A类的_a为1,B类中的_a为2。
若要实现b.print();输出2,可以在B中重写print函数实现。
例题5:
下面程序会在哪一行崩溃?
#include <stdio.h> struct S { int i; int *p; }; int main() { S s; int *p = &s.i; p[0] = 4; p[1] = 3; s.p = p; s.p[1] = 1; s.p[0] = 2; return 0; }
Answer:
struct S { int i; int *p; }; int main() { S s; int *p = &s.i; //即p指向s.i(p的内容为&s.i) ; p[0] = 4; //即s.i = 4; p[1] = 3; //即s.p = 3; s.p = p; //即s.p存了p的值,即&s.i; s.p[1] = 1; //s.p[1]即 *(&s.i + 1),也就是s.p。于是s.p[1] = 1;即s.p = 1; //s.p指向一个未作声明的地址0x00000001; s.p[0] = 2; //s.p[0] = 2;即对s.p指向的地址赋值,相当于*((int *)1) = 2; //此时对一个未作声明的地址赋值,程序崩溃。 return 0; }
例题6:(数组指针)。
解释a的输出结果。
int (*a)[10];
a++;
Answer:
编程测试如下。a是一个数组指针,指向一个大小为10的数组。
a++;表示a指针向后移动1 * sizeof(数组)的大小,即向后移动40个字节。
#include <stdio.h> int main() { int v[2][10]; int (*a)[10] = &v[0]; int (*tmp)[10] = a; a++; printf("%d\n", (int)a - (int)tmp); return 0; }
例题7:
空指针和迷途指针的区别?
代码:
#include <iostream.h> int main(){ int *pInt = new int; *pInt=10; cout<<*pInt<<endl; delete pInt; pInt=0;// 若未赋0,则变成迷途指针 *pInt=20; // oh no, this was deleled. cout<<*pInt<<endl; return 0; }
迷途指针也叫悬浮指针,失控指针,是对一个指针delete后---这样会释放它所指向的内存---并没有把它设置为空时产生的.
而后,如果你没有赋值就试图再次使用该指针,引起的结果是不可预料的.
当delete一个指针时,实际上仅是让编译器释放内存,但指针本身依然存在。这时它就是一个迷途指针。
当使用以下语句时,可以把迷途指针改为空指针:
MyPtr=0;
通常,如果在删除一个指针后又把它删除了一次,程序就会变得非常不稳定,任何情况都有可能发生。但是如果你只是删除了一个空指针,
则什么事都不会发生,这样做非常安全。
例题8:
C++中有了malloc / free,为什么还要new / delete ?
测试程序如下:
#include <stdio.h> #include <stdlib.h> class A { public: int a; A() { puts("调用构造函数!"); } ~A() { puts("调用析构函数!"); } }; int main() { puts("使用new申请空间"); A *a = new A(); delete a; puts("使用delete释放"); puts(""); puts("使用malloc申请空间"); A *b = (A *)malloc(sizeof(A)); free(b); puts("使用free释放"); return 0; }
运行一下上面的程序便知区别。
运行之后仍不解,可参看文字说明:
C++中有了malloc/free,为什么还需要new/delete?
原创文章如转载请注明:转自¥忘%风 {http://www.cnblogs.com/slave_wc}
本文地址: 指针与引用(面试宝典笔记三)