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);//没有这种用法

返回const 类型*的指针,表示不希望外部通过改指针改变指针指向的内容

// const AVCodec *avcodec_find_decoder(enum AVCodecID id);
const AVCodec *dec = avcodec_find_decoder(st->codecpar->codec_id);

这里就是不希望用户通过dec去改变指针指向的内容。

posted @ 2020-10-09 17:55  cyssmile  阅读(1422)  评论(0编辑  收藏  举报