指標與引用
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:
null 指標和迷途指標的區別?
代碼:
#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;
通常,如果在刪除一個指標後又把它刪除了一次,程式就會變得非常不穩定,任何情況都有可能發生。但是如果你只是刪除了一個null 指標,
則什麼事都不會發生,這樣做非常安全。
使用迷途指標或null 指標(如MyPtr=0)是非法的,而且有可能造成程式崩潰。如果指標是使用null 指標,儘管同樣是崩潰,但它同迷途指標造成的崩潰相比是一種可預料的崩潰。這樣調試起來會方便的多
例題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}
本文地址: 指標與引用(面試寶典筆記三)