C++原始指针的补充
曾经沧海难为水,除却巫山不是云。
取次花丛懒回顾,半缘修道半缘君。——《离思五首·其四》【元稹〔唐代〕】
目录
回忆:
正文:
1. const的先后问题:
例子:
代码演示:
提升拓展:左值和右值:
左值:
右值:
2.指向指针的指针:
下期预告:C++指针的基本操作(1)
回忆:
上次的C++原始指针我们没有说完,今天算是上一期的补充。在开始之前大家请回忆回忆我们上期讲到的三个原始指针都是什么,都分别有什么作用。现在让我们一起想一想,我们上期一共说了【一般指针,指针数组,数组指针】;其中需要重点记忆和理解的是数组指针,和指针数组(它们之间的区别和概念,所表达的有什么区别)。
记不清的同学可以看一看我上一期的内容:C++中一般指针,指针数组,数组指针
正文:
现在我们来开始今天的内容:
1. const的先后问题:
我相信大家一定见过const。不管是写代码,还是看代码,const都是一个很常见的符号。首先我们要清楚const其实就是对编译器说我们要编写的这个东西是常量,不能在后续的代码过程中改变它的内容。这就引出了我们的第一个问题:const的先后问题。由于我们讲的是指针,指针有指向和其指向的内容两部分。所以我们的const的位置就有三种情况(大家可以打开脑洞想一想,学习新知识就是这样,要有自己的思考,然后再学习知识就会简单很多)。
例子:
char s[]={"my name is sam"};
char const*a="my name is sam";
char* const b="my name is sam";
char const*const c="my name is sam";
判断:
a=s;
b=s;
c=s;
大家看一下上面的例子,猜一猜下面三行代码有几个是对的,有几个是错的。
现在揭晓:只有a=s;是对的,剩余的两个都是错的。下面就来讲一讲我们const具体的用法。
关于const起作用的部分:
1.看左侧最近的部分。
2.如果我们没有左侧,那就看右侧的。
这下我们再来看上面的代码,我们来逐行分析:首先我们定义了一个名为s的字符数组,并初始化对其赋值。然后我们再定义三个字符指针然后赋值。不同地就是const的位置。指针a我们的const修饰的是左侧的char,这就导致我们无法修改指针a指向的值(也就是我们无法修改"my name is sam"),但是我们可以修改a的指向,所以我们只有a=s;是正确的。在指针b中我们的const也是中间,修饰的同样是左侧,但是我们的左侧换成了char*,是指针,这就导致我们无法修改指针b的指向,我们只能修改其指向的值,所以b=s;是错的。指针c我们发现有两个const,其实就是上面两种方法的结合,指针c我们无法修改其指向,也无法修改其指向的值(算是融合怪)。
代码演示:
include<iostream>
using namespace std;
int MAX_LEN;
int main()
{
char s[]={"my name is sam"};char const*a="my name is sam"; //const char*char* const b="my name is sam"; char const*const c="my name is sam"; //const char* consta=s;//b=s; 错误//c=s; 错误int len=strlen_s(b,MAX_LEN);
cout<<len;
for(int i=0;i<len;++i)
{
//a=s[i]+1;值无法改变
b=s[i]+1;
//c=s[i]+1;值无法改变
}
return 0;
}
大家看上面的代码,我们在下方又写了一部分代码,我们先利用安全级高的strlen_s来求出b的长度,因为指针的初始化都是相同的,所以他们的大小长度也是一样的。然后我们用一个循环验证我们上面说到的解析。我们的a和c是无法改变其值,但是b可以改变。如果我们不注释那几行代码的话,我们就会看到编译器提醒我们要写一个左值。
提升拓展:左值和右值:
左值:
1. 左值的基本概念
定义:左值(lvalue)是C++中的一个表达式,它表示一个对象的位置,且该位置在表达式的求值过程中保持不变。简单来说,左值指的是可以出现在赋值语句左边的实体,代表一块有名字的、可以取地址的内存。
2. 左值的特性与要求
特性:左值具有持久性和可定位性。持久性意味着左值不是临时的,它在内存中有明确的存储位置;可定位性则意味着可以通过取地址操作符(&)获取其内存地址。
要求:为了成为一个左值,一个表达式必须能够标识一个具体的内存位置,以便可以对其进行赋值或其他操作。
3. 左值在C++中的使用场景
赋值操作:左值最常见的用途是作为赋值语句的左侧操作数,用于接收右侧操作数的值。例如,在语句“int a; a = 5;”中,“a”就是一个左值。
引用绑定:在C++中,引用(reference)必须与左值进行绑定。这是因为引用需要提供一个持久的内存位置来存储其引用的对象的地址。
4. 与左值相关的其他概念
右值(rvalue):与左值相对的是右值,它表示一个临时的、不可定位的值。右值通常出现在赋值语句的右侧,用于提供要赋给左值的值。例如,在语句“int a = 5;”中,“5”就是一个右值。
左值引用(lvalue reference):左值引用是C++11引入的新特性,用于绑定到左值上。左值引用允许我们创建一个别名来访问已经存在的对象,从而可以更方便地操作这些对象。
右值引用(rvalue reference):同样是在C++11中引入的,右值引用允许我们绑定到右值上,从而可以实现对临时对象的移动语义和完美转发等高级功能。这有助于提高代码的性能和灵活性。右值:
1. C++右值的基本概念
定义:在C++中,右值(rvalue)是指那些只能出现在赋值操作或其他表达式右边的值。它们通常表示临时的、不可寻。
与左值的区别:与左值(lvalue)相比,右值不代表内存中持久的对象,而是临时的、在表达式结束后就可能被销毁的值。
2. 右值的特性与分类
特性:
临时性:右值往往是表达式计算过程中临时产生的值。
不可寻址性:无法获取右值的内存地址,即不能使用取地址操作符(&)。
分类:
纯右值(Pure Rvalue):如字面量(如42、'a')或临时对象(如函数返回的临时对象)。
将亡值(Xvalue):一种特殊的右值,表示即将被移动的对象。它可以通过std::move函数从左值转换而来。
3. 右值在C++中的用途与优势
用途:
支持移动语义:通过移动构造函数和移动赋值运算符,可以安全地“窃取”右值的资源,从而提高代码性能。
完美转发:在模板编程中,右值引用可以与std::forward结合使用,实现参数的完美转发。
优势:
性能提升:通过减少不必要的拷贝操作,右值引用可以显著提高程序的性能。
资源管理:右值引用提供了一种更安全、更高效的方式来管理资源,如动态分配的内存。
4. 与右值相关的C++特性
右值引用(Rvalue Reference):C++11引入的新特性,用于绑定到右值上。它允许我们定义专门处理右值的函数重载,从而实现移动语义和完美转发。
移动语义(Move Semantics):通过移动构造函数和移动赋值运算符,可以将资源从一个对象“移动”到另一个对象,而不是进行拷贝。这通常涉及将源对象的内部指针或句柄设置为nullptr,并将这些资源转移到目标对象中。
std::move函数:一个标准库函数,用于将其参数转换为右值引用。它本身并不移动任何数据,而是提供了一种方式来指示编译器应该使用移动语义而不是拷贝语义。需要注意的是,std::move并不总是安全的或合适的,应谨慎使用。
上面就是关于左值,右值的一些基本知识,大家理解性记忆。
2.指向指针的指针:
例子:
int a=123;
int*b=&a;
int**c=&b;
规则:
*操作符具有从右向左的结合性:
**c这个表达式相当于*(*c),必须从这里想外逐层求解。
*c得到的其实就是b,也是&a。
**c得到的是*b,也就是a的值。
表达式 | 表达式的值 |
a | 123 |
b | &a 123 |
*b | a 123 |
c | &b |
*c | b &a |
**c | *b a 123 |
这就是双重指针的基本规则,其实就是嵌套指针。
🆗到这里,这篇关于:C++原始指针的补充就说完了,求一个免费的赞,感谢阅读。