1. 程式人生 > 實用技巧 >【C++學習教程06】指標

【C++學習教程06】指標

目錄

參考資料

  • 範磊C++(第8課)
  • VS2015

指標

指標的基本概念

空指標

指標與型別

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
	double a = 3.14;
	cout << "double is " << sizeof(a) << "byte" << endl;
	int b = 6;
	cout << "int is " << sizeof(b) << "byte" << endl;
	int *p1 = &b;
	double *p2 = &a;
	cout << "double adress is:" << p2 << endl;
	cout << "int adress is:" << p1 << endl;
	p1++;
	p2++;
	cout << "after move" << endl;
	cout << "double adress is:" << p2 << endl;
	cout << "int adress is:" << p1 << endl;
	system("pause");
	return 0;
}

結果:

用指標來訪問

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
	double a = 3.14;
	cout << "double is " << sizeof(a) << "byte" << endl;
	int b = 6;
	cout << "int is " << sizeof(b) << "byte" << endl;
	int *p1 = &b;
	double *p2 = &a;
	cout << "double adress is:" << p2 << endl;
	cout << "int adress is:" << p1 << endl;
	cout << "double num is:" << *p2 << endl;
	cout << "int num is:" << *p1 << endl;
	p1++;
	p2++;
	cout << "after move" << endl;
	cout << "double adress is:" << p2 << endl;
	cout << "num is:" << *p2 << endl;
	cout << "int adress is:" << p1 << endl;
	cout << "num is:" << *p1 << endl;
	system("pause");
	return 0;
}

執行結果:

容易混淆的概念

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int i=1;
    int *p=NULL;
    cout<<"i的值:"<<i<<endl;
    cout<<"i的地址:"<<&i<<endl;
    cout<<"p的值:(P所儲存的地址)"<<p<<endl;
    //cout<<"p所指向地址的值"<<*p<<endl;//訪問零脂針會發生報錯“程式崩潰“
    cout<<"p的地址:"<<&p<<endl;
    p=&i;
    cout<<"賦值後"<<endl;
    cout<<"p的值:(P所儲存的地址)"<<p<<endl;
    cout<<"p所指向地址的值"<<*p<<endl;
    cout<<"p的地址:"<<&p<<endl;
    return 0;
}

執行後結果:

指標對數值的操作

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    typedef unsigned short int ut;
    cout<<sizeof(ut)<<endl;//2個位元組
    ut i=5;
    ut *p=NULL;
    p=&i;
    cout<<"i="<<i<<endl;
    cout<<"*p="<<*p<<endl;
    cout<<"用脂針來修改存放在i中的資料"<<endl;
    *p=90;
    cout<<"i="<<i<<endl;
    cout<<"*p="<<*p<<endl;
    cout<<"用i來修改存放在i中的資料"<<endl;
    i=9;
    cout<<"i="<<i<<endl;
    cout<<"*p="<<*p<<endl;
    return 0;
}

輸出結果:

為什麼使用指標

棧和堆

  • 棧的資料壽命短但全域性區是在程式結束後才能完全釋放;
  • 堆可以由程式設計師決定,自由度高,優於棧和全域性區;
  • 堆是通過匿名的方式來儲存資料的,只能通過指標才能訪問到這些匿名的資料。他的安全性是最好的。

以下為詳細解釋:

⬆️合理利用記憶體空間

⬆️ 空間使用靈活

用圖來解釋棧的工作原理:

對於堆來說:

總結:

指標與堆

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p1;
    p1=new int;//new建立堆變數
    cout<<p1<<endl;
    double *p2=new double;
    cout<<p2<<endl;
    return 0;
}

輸出:

用指標刪除堆中的空間

記憶體洩露

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // insert code here...
    int *p=new int;//new建立堆變數
    *p=36000;
    cout<<*p<<endl;
    delete p;//釋放記憶體而不刪除指標
    cout<<*p<<endl;
    p=NULL;
    p=new int;
    *p=8;
    cout<<*p<<endl;
    delete p;
    cout<<*p<<endl;
    //delete p;//反覆delete會導致程式崩潰
    return 0;
}

執行結果:

在這裡記憶體並沒有被釋放掉,值得深思。

  • VS2015
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
	int *p = new int;
	*p = 23;
	delete p;
	cout << *p << endl;
	system("pause");
	return 0;
}

輸出結果:

參考連結: 某論壇.

記憶體洩漏

在堆中建立物件與刪除物件&訪問堆中的成員資料

#include <iostream>
using namespace std;
class Human
{
public:
    Human(){cout<<"建構函式執行"<<endl; i=9999;}
    ~Human(){cout<<"解構函式執行"<<endl;}
    int get()const{return i;}
private:
    int i;
};
int main(int argc, const char * argv[]) {
    Human Jack; //呼叫存放在棧中物件的方法
    cout<<Jack.get()<<endl;
    cout<<"************"<<endl;
    //以下存放在為堆中的物件
    Human *p=new Human;//此時已經建立了一個human類的物件!!他是一個匿名的!!!只能用指標找到他。
    cout<<p->get()<<endl;
    delete p;//刪除這個物件也可以用p
    return 0;
}//棧中的物件會在遇到}自動析構掉

this指標

//
#include <iostream>
using namespace std;
class A
{
public:
    int get()const{return i;}
    void set(int x){i=x; cout<<"this變數儲存的記憶體:\t"<<this<<endl;}
private:
    int i;
};
int main(int argc, const char * argv[]) {
    A a;
    a.set(9);
    cout<<"物件a的記憶體地址:\t"<<&a<<endl;
    cout<<a.get()<<endl;
    
    A b;
    b.set(9);
    cout<<"物件b的記憶體地址:\t"<<&b<<endl;
    cout<<b.get()<<endl;
    
    return 0;
}

輸出結果:

指標的常見錯誤

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    int *p=new int;
    *p=3;
    cout<<"將3付給p的地址後,讀取指標p的值:\t"<<*p<<endl;
    delete p;
    //p=NULL;//用程式崩潰的代價來保證不會引起使用野指標
    cout<<"刪除空間後,讀取指標p的值:\t"<<*p<<endl;
    long *p1=new long;//p1指向了p所釋放的空間
    cout<<"建立新空間後,指標p儲存的地址:\t"<<p<<endl;
    *p1=9999;
    cout<<"指向新空間的指標P1儲存的地址:\t"<<p<<endl;
    *p=23;//其實是將23賦給P1指向的記憶體空間
    cout<<"將23付給p的地址後,讀取指標p的值:\t"<<*p<<endl;
    cout<<"將23付給p的地址後,讀取指標p1的值:\t"<<*p1<<endl;
    return 0;
}

輸出結果:

常量指標和指向常量的指標

常量指標


指向常量的指標


指向常量的常指標

及上面兩個的結合,指標和指向的目標都不能改變。

總結