1.理解const*
與*const
假設有一個ptr指針,它保存變量vbl的地址。
Type* ptr = &vbl;
當使用指針的時候就涉及到兩個對象:指針本身以及本身所指的對象。這就意味着const有三個層級的保護。
1.1. 確保ptr指向唯一的內存
有兩種寫法
Type* const ptr = &vbl;
Type* const ptr(&vbl);
1.2. 確保不能通過ptr改變vbl的值
const Type* ptr = &vbl;
const Type* ptr(&vbl);
1.3. 希望兩者都不會改變
const Type* const ptr = &vbl;
const Type* const ptr(&vbl);
1.4. 怎么記憶呢
從右邊向左讀
const char* x = &p; /* x 是一個指針,指向 常char的對象*/
char* const x = &p; /* x 是一個常指針,指向char的對象*/
const char* const x = &p; /* x 是一個常指針,指向常char的對象*/
可以把常改成不可變,就好讀了。
2.const*
與*
作為函數參數的差別
const*
與*
作為函數參數的情況
1. 不管是const*
還是*
在作為函數傳遞的時候都是值傳遞。
#include <iostream>
#include <stdio.h>
struct A {
int a = 0;
float b = 0.0f;
};
void Test_Const(const A* ptr) {
A* tmp = new A();
ptr = tmp;
printf("Test_Const &tmp: %p\n",tmp);
printf("Test_Const ptr: %p\n",ptr);
}
void Test_Ptr(A* ptr) {
A* tmp = new A();
printf("Test_Ptr &tmp: %p\n",tmp);
ptr = tmp;
printf("Test_Ptr ptr: %p\n",ptr);
}
int main() {
A a;
A* ptr = &a;
printf("&a: %p\n",ptr);
Test_Const(ptr);
printf("&a: %p\n",ptr);
A* t_ptr = &a;
Test_Ptr(t_ptr);
printf("&a: %p\n",t_ptr);
return 0;
}
運行結果
這里我做了個實驗,這里new的資源釋放,不要在意這些細節。我的想法是一個以const*
作為參數一個以*
作為參數。發現在函數里面這個指針都是可以指向其他地方的。
但是函數外面這個指針值是沒改變的,所以推斷const*
和*
這個指針值傳的時候都是值傳遞的。
2.2. const*
作為函數參數傳遞的時候
不允許將這個指針復制給其他非常指針
2.3. *
作為函數參數傳遞的時候
允許將這個指針復制給其他非常指針或常指針
2.4. const*&
與 *&
*&
是允許改變指針的值的
#include <iostream>
#include <stdio.h>
struct A {
int a = 0;
float b = 0.0f;
};
void Test_Ptr(A*& ptr) {
A* tmp = new A();
printf("Test_Ptr &tmp: %p\n",tmp);
ptr = tmp;
printf("Test_Ptr ptr: %p\n",ptr);
}
int main() {
A a;
A* ptr = &a;
printf("&a: %p\n",ptr);
A* t_ptr = &a;
Test_Ptr(t_ptr);
printf("&a: %p\n",t_ptr);
return 0;
}
運行結果
2.5. const*&
應該沒這種用法
編譯的時候會報這個錯
invalid initialization of non-const reference of type
那么對於這里應該怎么改呢
按照我們這意思就應該
void Test_Const(const A*& ptr)
改成
void Test_Const(const A* const & ptr)
於是我們可以進一步的將*&
寫成*const&
void Test_Ptr(A* const & ptr)
最后理解下這幾種寫法
void Test_Ptr(A* ptr); // 傳指針,可以改變指針指向內容,可以在函數將其他指針賦值給ptr,但是不會改變函數外ptr的值。
void Test_Ptr(const A* ptr); //不可改變函數指向的值(不能通過該指針),可以在函數內將其他的指針賦值給ptr,不會改變函數外ptr的值
void Test_Ptr(A*& ptr); //以引用的方式傳遞指針,既可以改變指針本身也可改變指針指向的內容,函數內外都可見
void Test_Ptr(A* cosnt & ptr); //以引用的方式傳遞指針,可以改變指針指向的內容,但是不能改變指針本身指向的地址。
void Test_Ptr(const A* cosnt & ptr); //以引用的方式傳遞,不能改變指針值以及指針指向的內容
void Test_Ptr(const A*& ptr);//沒有這種用法