博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

指针与引用(面试宝典笔记三)

Posted on 2011-04-07 20:55  ¥忘%风  阅读(2825)  评论(10编辑  收藏  举报
指针与引用
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;
}
 Answer:
错误:7,11,13行。
7:引用必须在声明时同时初始化。
11:pi没有指向,不可以对其赋值。
13: 本地的const常量必须在第一次声明时就初始化。


例题2:
这个程序有什么问题?该如何修改? 
char *strA() {
    char str[] = “Hello World”;
    return str;
}
Answer:
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;
}
//注:若调换sp[1] = 1;和s.p[0] = 2;的顺序,程序可正常运行。

 测试截图:win下vs2010

linux下eclipse运行:



例题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;

通常,如果在删除一个指针后又把它删除了一次,程序就会变得非常不稳定,任何情况都有可能发生。但是如果你只是删除了一个空指针,

则什么事都不会发生,这样做非常安全。

使用迷途指针或空指针(如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}

本文地址: 指针与引用(面试宝典笔记三)