const*與*const以及const*與*作為函數參數的差別


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);//沒有這種用法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM