溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中指針怎么使用

發(fā)布時間:2022-03-28 09:18:18 來源:億速云 閱讀:156 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)C++中指針怎么使用的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

指針為什么要有類型

是為了指針運算和取值。

當使用指針取值的時候需要知道怎么取值,比如按照多少個字節(jié)去取值,這是需要確定才能取到正確的值的,要知道用多少個字節(jié)去取就得知道指針的類型是什么。

我們知道指針的運算增加或者減少1意味著需要偏移指針所表示的類型的大小個字節(jié)數(shù),比如說一個int字節(jié)的指針增加1,表示偏移4個字節(jié)(一般情況下int都是4個字節(jié)),所以這也是需要知道指針的類型。

指針和數(shù)組

本來從字面上來說指針和數(shù)組是八竿子打不著的,它們理應是井水不犯河水的,怎么就扯上了呢?我們經(jīng)常聽說數(shù)組指針、指針數(shù)組,這些都是什么意思呢?他們到底是指針還是數(shù)組呢?下面將一一為你解答。

指針數(shù)組,首先它是一個數(shù)組,數(shù)組里面的每個元素都是一個指針,例如比如int *p[4] 就是一個指針數(shù)組,因為運算符[]的優(yōu)先級運算符*的優(yōu)先級高,所以p優(yōu)先和[]組成數(shù)組,然后*和類型int組合成數(shù)組元素的類型。 例如以下程序就是一個指針數(shù)組的示例:

main.c
#include <stdio.h>
int main(){
    char *str[3] = {
        "我是數(shù)組1",
        "我是數(shù)組2",
        "我是數(shù)組3"
    };
    printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
    return 0;
}

數(shù)組指針,首先它是一個指針,這個指針所指向的對象是數(shù)組,比如這個指針是p,那么通過解引用*p獲得內(nèi)容就是一個數(shù)組,例如int (*p)[4],主意帶上括號, 通常數(shù)組指針也作為一個二維數(shù)組來使用。

二級指針

所謂的二級指針其實就是一個指向指針的指針,例如int **p就是一個二級指針,它內(nèi)部存放的對象是一個指針,通過一次解引用獲得的是內(nèi)存存放的指針的地址,需要再次對這個內(nèi)部的指針進行解引用才能獲取到 這個真是內(nèi)容的值。

理解起來有點繞,那么這個拗口的二級指針有什么作用呢?二級指針在C++中可能用的不多,但是在C中是經(jīng)常使用的一把利器,它通常作為一個函數(shù)的參數(shù),起到在函數(shù)內(nèi)部對一個指針進行初始化的作用, 比如經(jīng)典的音視頻處理工具FFmpeg中就大量使用了二級指針。 以下例子展示如何通過二級指針對指針形式賦值:

main.cpp
void initP(int **p){
    *p = new int(10);
}

int main() {
    int *p = nullptr; // 一個空的指針
    initP(&p); // 通過二級指針初始化指針p
    std::cout << "*p的值:" << *p << endl;
    delete p;
    return 0;
}

可能在這里就有人和當初筆者剛接觸C語言一樣迷惑了,難道不能通過給函數(shù)傳遞一級指針給指針初始化嗎?這是不行的,這是因為值傳遞的緣故,像深入探討的童鞋們可以寫個例子打印下實參的具體地址對比下研究下其背后的原理。

指針與多態(tài)綁定

我們都知道C++是一門面向?qū)ο蟮脑O計語言,支持多態(tài)就是它的一個重要特性之一,在學習C++類的相關(guān)知識的時候老師就告訴我們:*在C++語言中,當我們使用基類的引用(或指針)調(diào)用一個虛函數(shù)時將發(fā)生動態(tài)綁定。*也就是 說使用通過父類的指針或引用就能按照實參的實際類型是父類還是子類調(diào)用不同的虛函數(shù)。

例如如以下代碼:

main.cpp
class Base{
public:
    virtual void print() const{
        std::cout << "base print" << endl;
    }
    virtual ~Base(){
    }
};

class Child:public Base{
public:
    void print() const override{
        std::cout << "Child print" << endl;
    }
};

void testPrint(const Base &base){
    base.print();
}

int main() {
    Base a = Child();
    testPrint(a);// 打印Base print
    Child b = Child(); // 注意,不能寫成Base b = Child(),否則打印的是Base的print
    testPrint(b); // 打印Child print
    Base *c = new Child(); // 指針,動態(tài)類型與靜態(tài)類型不一致
    testPrint(*c); // 打印Child print

    Base &&r = Child(); // 表達式是右值引用,動態(tài)類型與靜態(tài)類型不一致
    testPrint(r); // 打印Child print
    return 0;
}

為什么在上面的程序中變量a的實際類型是Child,但是函數(shù)testPrint內(nèi)部調(diào)用的卻是父類的打印方法呢?不是說引用會觸發(fā)多態(tài)嗎?函數(shù)testPrint也是通過引用傳遞的呀, 真是百思不得其jie呀。

要解開這個疑惑就得了解下靜態(tài)類型和動態(tài)類型的知識了。靜態(tài)類型在編譯時總是已知的,首先靜態(tài)類型是變量聲明時的類型或表達式生成的類型;動態(tài)類型則是變量或表達式表示的內(nèi)存中的對象的類型,動態(tài)類型直到運行時才可知。 如果變量在定義時表達式既不是引用也不是指針,則它的動態(tài)類型永遠與靜態(tài)類型一致的,也就是聲明時所指的類型,否則的話靜態(tài)類型可能與動態(tài)類型不一致。

那么有了靜態(tài)類型與動態(tài)類型的概念之后再結(jié)合注釋看上面的示例代碼是不是就有一種撥開云霧見青天的感覺了呢?

函數(shù)指針

函數(shù)指針顧名思義就是指向函數(shù)的指針,它的定義:函數(shù)指針是指向函數(shù)的指針變量。因此“函數(shù)指針”本身首先應是指針變量,只不過該指針變量指向函數(shù)。

其聲明方式是:

返回值類型 (*函數(shù)名) (參數(shù))  

函數(shù)指針的一個重要用途就是作為函數(shù)的參數(shù),用于在函數(shù)內(nèi)部進行指針函數(shù)的調(diào)用,一般用作回調(diào)函數(shù),比如在創(chuàng)建一個POSIX線程的就需要傳遞一個函數(shù)指針用于指明該線程做點什么事情。

以下代碼展示了一個簡單的函數(shù)指針的使用方法:

void testFunc(int a,int b,void (*func)(int c,int d) ){
    // do something
    func(a,b);
}

void callback(int a,int b){
}

int main() {
    testFunc(1,2,callback);
    return 0;
}

類成員指針

這里類成員指針表示的是指向類的某個對象的非靜態(tài)成員的指針,而不是表示類成員變量的指針,首先需要區(qū)分好這是兩個不同的概念,如果不能好好區(qū)分這兩個概念的童鞋,需要再好好思考一下。

成員指針的類型囊括了類的類型以及成員的類型。當初始化一個這樣的指針時,我們令其指向類的某個成員,但是不指定該成員所屬的對象;直到使用成員指針時,才提供成員所屬的對象。

和其他指針一樣,在聲明成員指針時我們也使用*來表示當前聲明的名字是一個指針。與普通指針不同的是,成員指針還必須包含成員所屬的類。下面是一個使用的示例:

class Person{
public:
    virtual void print() const{
        std::cout << "base print" << endl;
    }

    virtual ~Person(){
    }

public:
    string lastName;
    string firstName;
};

int main() {
    string Person::*p; // 聲明了一個類成員指針
    p = &Person::firstName; // 成員變量的指針指向了Peron的name
    Person person;
    person.*p = "hello"; // 使用成員指針
    p = &Person::lastName; // 成員變量的指針指向了Peron的lastName
    person.*p = "world"; // 使用成員指針
    std::cout << person.firstName << " " << person.lastName << std::endl;
    return 0;
}

至于這個成員指針有什么用處,給筆者的感覺就是重新命了一個別名的感覺,甚至有點脫褲子放屁?但是存在即合理,不是沒有用處,只是筆者見過那種場景而已吧。。。

除了有指向類成員變量的指針外還有指向類成員函數(shù)的指針,這里就不多展開探討了!??!

補充:用指針的指針指向指針數(shù)組

#include<stdio.h> 
int change(char **p)
{
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; *(*(p + i) + j) != '\0'; j++)//利用指針的指針取二維數(shù)組的元素
		{
			*(*(p + i) + j) = 'c';
			printf("%c", *(*(p + i) + j));
		}
		printf("\n");
	}
	return 0;
}
 
int main(void)
{
	char *a[5] = { "hello", "zhuyu", "jiajia", "linux","Ubuntu" };//如果想使用 需使用指針數(shù)組即*a[5] 聲明一個有五個字符串指針的數(shù)組。
	                                                              //但是由于每個元素都是指針字符串,所以只能夠讀取,而不能夠?qū)懭搿?
	change(a);
	return 0;
}

感謝各位的閱讀!關(guān)于“C++中指針怎么使用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI