【C++】关于常引用的问题 #什么是权限放大?权限放小?隐式或强制转换居然还有这一步?...#

简介: 【C++】关于常引用的问题 #什么是权限放大?权限放小?隐式或强制转换居然还有这一步?...#

前言


引用c++中的使用非常常见,可以说是很重要的,引用常引用相关的问题让很多人稍不留神就出错了,这里我们就来谈谈常引用的问题。


关于权限


  • 关于权限有权限缩小和权限放大的问题,比如一个文件,当初它只有读的权限,而现在你给它再加个写的权限,这就是权限放大;又或当初它读,写的权限都有,但你把他某个权限或所有权限都限制了,这就是权限缩小。
  • 在指针和引用赋值中,权限可以缩小,但不可以放大:这里通常指的是变量的值可不可以改的问题,如果说是从改到不能改,这就是将权限缩小了,这是可行的;如果说是从不能改到能改,这就是权限放大了,此时是不行的。
  • 而引用相当于起别名,对于这个别名的权限相对于本名变量有什么变化,这需要自己来决定。当自己决定别名的权限之后(不能与第二点表达的起冲突),对它的使用就要留个心眼。


关于引用与const


const通常就是用来限制变量可以改,也就是这个变量的值不能被修改,结合上面的权限问题,我们来看以下例子:

1.
int a = 10;
const int& ra = a;  // ??
int& raa = ra;  // ??
2.
const int b = 20;
int& rb = b;  // ??
const int& rrb = b;  // ??


对于上述代码的第一种情况:


关于ra,ra是a的别名,并且被const修饰,此时ra的值是不能被修改的(要注意,这里单指ra,只是说不能使用ra对a的值进行修改,使用a修改值还是可以的,注意是单指ra这个别名),由a到ra,很明显改的权限没了,属于权限变小,是可行的。

关于rra,rra是ra的别名,也就是a的别名的别名,本质还是一样的,只不过说,rra是相对于ra起的别名,ra的权限不能改,而rra前面没有const(能读能改),所以由ra到rra属于权限放大,是不可行的。

对于上述代码的第二种情况:


关于 rb ,rb是b的别名,b前面使用了const修饰,说明它不能被修改,而rb前面没有const,说明可读可改,属于权限放大,是不可行的。

关于rrb,rrb也是b的别名,b前面使用了const修饰,rrb前面也使用了const修饰,权限没有变,当然可行。


当我们在使用引用的时候,若是有const出现,那一定要注意权限的问题,不然程序写完一运行全是问题。


关于那秘密的一步


这秘密的一步还是与权限有关,居然是与权限有关,那么指向的对象就只有指针和引用了。


对于这秘密的一步,我们先来看以下例子:

  double b = 13.14;
//1.
  int a = b;  // 隐式类型转换
  int c = (int)b;  // 强制类型转换
//2.
  // 2.1. // 隐式类型转换
  int& rb = b;   // 出错   
  const int& rrb = b;
  // 2.2.  // 强制类型转换
  int& rrrb = (int)b;   // 出错
  const int& rrrrb = (int)b;


情况1:对于情况1,据前面的概念,变量a和c既不是指针也不是引用,所以这里当然是可行的。

情况2:

2.1: rb是b的别名,只不过rb的类型是(int),b的类型是(double),所以b发生了隐式类型转换,那么这里为什么会出错呢?就是因为那秘密的一步:b的隐式类型转换,转换后的值会先交给一个临时变量tmp(此时tmp变为13),而语法规定,这个tmp是一个常量,当tmp的值再交给rb时,rb是一个别名,前面没有const修饰,具有改的权限,所以这里权限是放大了的,是不可行的。也因此这里会出错。而下一条语句,rrb前面有const修饰,所以没有出错。

2.2:有了2.1的铺垫,实际上强转不强转的无所谓,最终还是归咎到有关const的权限问题,所以要理解那个tmp,也因此这里的rrrb会出错。


当然,对于函数调用,也有相关问题:

1.
void fun(int& rb)  // 权限放大,不行
{
  cout << rb << endl;
}
double b = 13.14;
fun(b); // 隐式类型转换交给一个临时变量,这个临时变量是常量
2.
void fun(const int& rb)  // 权限不变,可行
{
  cout << rb << endl;
}
double b = 13.14;
fun(b); // 隐式类型转换交给一个临时变量,这个临时变量是常量


无论是函数的传参还是返回,都存在那个临时变量的问题,规定了临时变量是一个常量,那就要小心这个点带来的问题。

对于1,2,关注的点还是一样的,都是围绕一个权限的问题,所以当我们在对函数传参或者是接收函数返回值的时候,要注意要不要加const,这样才能在小的细节上不会出错。


写在最后


最后还是要强调,关于本章内容,一定要清楚,不能搞混,谁知道在以后写代码的时候会不会出类似错误呢?而一旦出现此类的问题,那就很难受了。可能一时半会都想不清楚到底是哪出了问题。


感谢阅读本小白的博客,错误的地方请严厉指出噢!

相关文章
|
4月前
|
Rust NoSQL API
c++开发redis module问题之如果在加载module时,该module没有执行权限,Redis会如何解决
c++开发redis module问题之如果在加载module时,该module没有执行权限,Redis会如何解决
|
6月前
|
存储 数据安全/隐私保护 C++
第十五章:C++访问控制权限、继承和多态详解
第十五章:C++访问控制权限、继承和多态详解
288 0
|
6月前
|
存储 数据安全/隐私保护 C++
[C++从入门到精通] 1.函数调用、访问权限、类简介(Struct和Class区别)
[C++从入门到精通] 1.函数调用、访问权限、类简介(Struct和Class区别)
118 0
|
Java 程序员 C#
C++类成员的访问权限以及类的封装
C++通过 public、protected、private 三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的、受保护的、私有的,被称为成员访问限定符。所谓访问权限,就是你能不能使用该类中的成员。 Java、C# 程序员注意,C++ 中的 public、private、protected 只能修饰类的成员,不能修饰类,C++中的类没有共有私有之分。 在类的内部(定义类的代码内部),无论成员被声明为 public、protected 还是 private,都是可以互相访问的,没有访问权限的限制。 在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 p
104 0
|
编译器 数据安全/隐私保护 C语言
C++ 权限控制,权限的继承(下)
C++ 权限控制,权限的继承
|
编译器 数据安全/隐私保护 C语言
C++ 权限控制,权限的继承(上)
C++ 权限控制,权限的继承
|
C++
C++ protected权限成员以及类和结构体区别
我们已经知道在C++类中默认的访问权限是private,在C++结构体中默认的访问权限是public 其实在C++中类和结构体没有严格的界限,区别如上。 那么这里说明一下protected权限。
1303 0
|
6天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
29 4
|
7天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
25 4