指针与引用(面试宝典笔记三)
指针与引用
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}
本文地址: 指针与引用(面试宝典笔记三)