探究C++中指針與數(shù)組運算符優(yōu)先級
C++中與指針和數(shù)組相關的運算符優(yōu)先級,通過實際代碼示例解釋了運算符的左結合與右結合方式,以及如何使用圓括號()來改變默認的結合順序,文章還提供了一個優(yōu)先級表,列出了運算符的優(yōu)先級和結合性,幫助讀者更好地理解復雜表達式中運算符的調用順序,特別對于同時存在左結合和右結合運算符的情況,給出了詳細的分析和示例,使讀者能夠深入理解運算符優(yōu)先級的實際應用
指針、數(shù)組相關的運算符優(yōu)先級
下表展示了相關運算符的優(yōu)先級,有4個級別,同級別內的運算符按照結合性依次調用。這4類也是所有運算符中優(yōu)先級最高的4檔,其它的運算符優(yōu)先級都比它們低:
優(yōu)先級 | 運算符 | 描述 | 結合性 |
---|---|---|---|
1 | :: | 作用域解析 | 左結合 |
2 | () [] . -> | 強制運算結合,函數(shù)形參列表 數(shù)組元素下標訪問 類的成員訪問 類指針的成員訪問 | 右結合 |
3 | (int) * & | 強制轉換 指針解引用 變量取地址 | 左結合 |
4 | .* ->* | 類的成員函數(shù)指針 類指針的成員函數(shù)指針 | 左結合 |
容易產生困惑的、需要仔細進行優(yōu)先級判斷的往往是一個左結合加一個右結合,例如:
*ptr[]
(int)a()
&obj->data
obj->*fun()
請記住一個重要方法:當我們需要改變運算符的結合順序(C++默認的優(yōu)先級不是我們的意愿)時,可以通過添加()來人為強制指定優(yōu)先順序,因為()是除了::以外具有最高優(yōu)先級的一類運算符。
簡單例子:以[]和*為例探討運算符結合規(guī)律
下面的p1, p2是數(shù)組,p3是指針:
int *p1[2]; // p1是一個數(shù)組,元素個數(shù)為2,每個元素為(int*) int *(p2[2]); // 等價于*p2[2],p2是一個數(shù)組 int (*p3)[2]; // p3是一個指針,指向一個int數(shù)組,這個int數(shù)組的元素個數(shù)必須是2!
因此只要記住兩點即可:
- []的優(yōu)先級高于*:即
*p1[2]
和*(p1[2])
等價。 - 這個優(yōu)先級同時適用于定義語句(*為指針定義符)和執(zhí)行語句(*為解引用符)中:
int *p1[2]; // 定義語句:先看[]:p1是一個數(shù)組,元素個數(shù)為2,每個元素為(int*)。等價于*(p1[2]) int (*p2)[2]; // 定義語句:先看*: p2是一個指針,指向一個int數(shù)組,這個int數(shù)組的元素個數(shù)必須是2! cout << "*p1[0] = " << *p1[0] << endl; // 執(zhí)行語句:先看[]:先取第0個元素,再解引用。等價于*(p1[0]) cout << "(*p2)[0] = " << (*p2)[0] << endl; // 執(zhí)行語句:先看*:先解引用,再取第0個元素
完整示例:
#include <iostream> using namespace std; int main(){ // []的優(yōu)先級高于*,因此下面的p1是數(shù)組,p2是指針: int *p1[2]; // p1是一個數(shù)組,元素個數(shù)為2,每個元素為(int*)。等價于*(p1[2]) int (*p2)[2]; // p2是一個指針,指向一個int數(shù)組,這個int數(shù)組的元素個數(shù)必須是2! int a = 1, b = 2; int c[2] = {4,5}; p1[0] = &a; p1[1] = &b; p2 = &c; cout << "*p1[0] = " << *p1[0] << endl; cout << "*p1[1] = " << *p1[1] << endl; cout << "*(p1[0]) = " << *(p1[0]) << endl; // 與上面兩條等價 cout << "*(p1[1]) = " << *(p1[1]) << endl; cout << "(*p2)[0] = " << (*p2)[0] << endl; cout << "(*p2)[1] = " << (*p2)[1] << endl; return 0; }
輸出:
*p1[0] = 1 *p1[1] = 2 *(p1[0]) = 1 *(p1[1]) = 2 (*p2)[0] = 4 (*p2)[1] = 5
復雜例子:探討當左結合和右結合運算符同時存在時如何界定優(yōu)先級
下面的例子比較復雜,需要耐心仔細閱讀和體會。如果這個例子能搞清楚,那么相信你對運算符優(yōu)先級的理解將會上升一個檔次。
這個例子研究了當左結合和右結合運算符同時存在時的結合順序,同時也演示了可以使用()強制人為指定結合順序:
#include <iostream> #include <string> using namespace std; class Student{ public: Student(string name, int id):_name(name),_id(id){} void printInfo(){ cout << "I am a student. My name is " << _name << ". My id is " << _id << endl; } void operator()(){ printInfo(); } protected: string _name; int _id; }; class Student2 : public Student{ public: Student2(string name, int id):Student(name, id){} void printInfo(){ cout << "I am a super Student!!! " << endl; } void operator()(){ cout << "I am Student2!!!" << endl; } }; struct StudentWrapper{ Student* _ps; StudentWrapper(Student* ps):_ps(ps){} Student* operator()(){return _ps;} }; int main(){ // .和(), ->和()平級:從左向右 cout << "-----------------1------------------" << endl; Student s1("Bob",101), s2("Jack", 102); Student *ps1 = new Student("Eric",103); s1.printInfo(); s2.printInfo(); ps1->printInfo(); // .高于*:先結合. cout << "-----------------2------------------" << endl; // 下面這條語句報錯:先調用.printInfo(),再*,因此會報錯 // *ps1.printInfo(); // error: request for member 'printInfo' in 'ps1' (*ps1).printInfo(); // .和()高于*:先結合()和.(從右向左),最后結合* cout << "-----------------3------------------" << endl; StudentWrapper sw(ps1); // 下面這條語句報錯:先結合sw(),再結合.printInfo(),最后結合*,因此會報錯 // *sw().printInfo(); // error: request for member 'printInfo' in 'sw.StudentWrapper::operator()()' (*sw()).printInfo(); // correct:先sw(),再*sw(),再(*sw()).printInfo() // 下面這條語句報錯:先結合sw(),再結合(),最后結合*,因此會報錯 // *sw()(); // error: expression cannot be used as a function (*sw())(); // correct:先sw(),再*sw(),再(*sw())() // (int)和()/[]:先結合()和[],再強轉 cout << "-----------------4------------------" << endl; Student2 ss("Alice", 999), sss("Jason", 998), ssArray[2] = {ss, sss}; ss(); // 調用Student2::operator() // 下面這條語句報錯,因為會先結合ss(),再強制轉換 // (Student)ss(); // error: invalid use of void expression ((Student)ss)(); // correct: 調用Student::operator() // 下面這條語句報錯,因為會先結合ssArray[0], 再ssArray[0](),再強制轉換 // (Student)ssArray[0](); // error: invalid use of void expression ((Student)ssArray[1])(); // correct:將ssArray[1]強制轉換為Student類型后,調用其()方法 // ()高于.*和->*:先結合() cout << "-----------------5------------------" << endl; void (Student::*fp)(); fp = Student::printInfo; // s1.*fp(); // error: must use '.*' or '->*' to call pointer-to-member function in 'fp (...)' (s1.*fp)(); (s2.*fp)(); // ps1->*fp(); // error: must use '.*' or '->*' to call pointer-to-member function in 'fp (...)' (ps1->*fp)(); // (int)高于.*和->*:先結合(int) cout << "-----------------6------------------" << endl; Student2 *ssp = &sss; // Jason void (Student2::*fp2)(); fp2 = Student2::printInfo; (ss.*fp2)(); ((Student)ss.*fp)(); // 先將ss強轉為Student,然后調用Student::printInfo(),注意是.*fp而不是.*fp2 ((Student*)ssp->*fp)(); // 先將ssp強轉為Student*,然后調用Student::printInfo(),注意是.*fp而不是.*fp2 // *高于.*和->*:先結合* cout << "-----------------7------------------" << endl; (*ssp.*fp2)(); // 先*ssp,再.*fp2 Student2 **sspp = &ssp; (*sspp->*fp2)(); // 先*sspp,再->*fp2 delete ps1; return 0; }
輸出:
-----------------1------------------ I am a student. My name is Bob. My id is 101 I am a student. My name is Jack. My id is 102 I am a student. My name is Eric. My id is 103 -----------------2------------------ I am a student. My name is Eric. My id is 103 -----------------3------------------ I am a student. My name is Eric. My id is 103 I am a student. My name is Eric. My id is 103 -----------------4------------------ I am Student2!!! I am a student. My name is Alice. My id is 999 I am a student. My name is Jason. My id is 998 -----------------5------------------ I am a student. My name is Bob. My id is 101 I am a student. My name is Jack. My id is 102 I am a student. My name is Eric. My id is 103 -----------------6------------------ I am a super Student!!! I am a student. My name is Alice. My id is 999 I am a student. My name is Jason. My id is 998 -----------------7------------------ I am a super Student!!! I am a super Student!!!
到此這篇關于探究C++中指針與數(shù)組運算符優(yōu)先級的文章就介紹到這了,更多相關C++指針和數(shù)組運算符優(yōu)先級內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!