frankfan的胡思乱想

学海无涯,回头是岸

引用与默认参数

const 引用 默认参数
const关键词,引用的使用以及函数的默认参数。

const

C++中使用const来修饰变量,使其成为常量,所谓常量,就是只能在初始化时给定值,后续不支持再次修改其值。

要做到这个效果,除了在内存的语义上做限定使得内存的WRES中的只读属性设置为1外,const更多的是从编译器的层面来做限制,言外之意可以通过指针强转等方式绕过常量的限制,但这往往破坏了设计准则,带来潜在风险。

const能修饰所有的数据类型,并且是严格的修饰

#include <iostream>

struct Node{
  int value;
};
int main(){
  const int a = 11;
  //a = 12; 编译期报错
  
  const struct Node node = {11};
  //node.value = 12;编译期报错
  return 0;
}

const修饰指针,与const所处位置有关

总的原则是,const只影响其右侧最近的类型

#include <iostream>
int main(){
  
  int value = 11;
 
  //const修饰int*,因此指针为常量,无法通过指针pvalue修改值
  const int *pvalue = &value;
  //const修饰int*,因此指针为常量,无法通过指针pvalue修改值
  int const *pvalue2 = &value;
  /*
  *pvalue = 12;
  *pvalue2 = 12; 编译器报错*/
  
  //const修饰int,因此变量pvalue3为常量,不能再指向其他地址
  int *const pvalue3 = &value;
  //const既修饰int*,也修饰了int,因此既无法通过指针变量修改值,也无法重新指向其他地址
 	const int *const pvalue4 = &value;
  
  return 0;
}

关于const指针的强转

#include <iostream>

void func(const int *arr,int count){
  
  //arr[0] = 11;编译期错误
  //*(arr+0) = 11;编译期错误
  *(int*)(arr+0) = 11;//顺利通过
}

int main(){
  int a = 11;
  const *pa = &a;
  //*pa = 12; 无法直接通过这种形式修改变量a,编译器做了语法层面的限制
  *(int*)pa = 12;//但是可以通过强制转换类型的方式绕开限制
  return 0;
}

引用

C语言的指针既带来了方便也带来了风险,指针对内存的操作权限是无限制的,因此往往会带来不少的隐藏风险(如野指针等)。因此在C++中,推出了指针的限制版本,引用。既具备指针对内存操作的优势,而又做了一些使用上的限制,大大减少了风险。

#include <iostream>

void swap(int &a,int &b){
  int tmp = a;
  a = b;
  b = tmp;
}

int main(){

  //在定义指针时,可以不初始化,语法上并没有限制,而这个野指针就带了了风险。
  int *pa;
  int a = 11;
  pa = &a;
  *pa = 12;//需要通过取地址赋&以及*星号搭配使用
  
  //定义引用时,必须初始化,并且后续无法更改。
  int &refA = a;
  
  int v = 13;
  refA = v;//这只不过是对引用在赋值13而已,此时变量a的值是13
  
  int aa = 22,bb = 33;
  swap(aa,bb);//正常交换
  
  return 0;
}

任何数据类型都可以被引用,但是,引用无法被引用。存在指针的指针,但是不存在引用的引用。

这样就再一次限制了引用的出错机会

#include <iostream>
int main(){
  
  int a = 11;
  int *pa = &a;
  int* &rPa = pa;//指针类型引用
  *rPa = 12;
  cout<<a<<endl;//输出12
 	
  int &ra = a;
  //int &&raa = ra; 编译期报错,不支持
  
  return 0;
}

const引用

#include <iostream>
struct Node{
  int value1;
  int value2;
};
int main(){
  
	Node node = {11,12};
  const Node &rNode = node;
  //rNode.value = 13;编译期报错
  return 0;
}

实质上,引用的本质还是指针,不过是受限的指针

函数的默认参数

C++支持给函数的形参提供默认值,大大提高了函数的灵活性

#include <iostream>

void func(int a,int b = 12){
  cout<<a<<" "<<b<<endl;
}

//默认参数只有从右往左提供 void demo(int a = 11,int b,int c = 12);这是错误的❌

void func2(int a,int b,int c = 11){
  //do something
}

//当函数的声明与实现分离是,默认参数只能写在函数的声明中
void func3(int a,int b = 12);

int main(){
  func(11);//输出11 12
  func(11,22)//输出11 22
  return 0;
}
void func3(int a,int b){
  //do something....
}

posted on 2021-12-28 09:28  shadow_fan  阅读(223)  评论(0编辑  收藏  举报

导航