参考文献
右引用
问题的开始
好久没有练习c++,在数据结构中学习到了串这个数据结构,我便使用c++自己慢慢摸索实现了一下。当然我也遇到了不少问题。
在coding的时候要时不时查阅自己的c++ 笔记,当然我也遇到了没有学习过的知识点,特此记录一下!
下面图片中 S1 S2 S3 都是自己正在完善的 String类的变量
S4 = S1 + S3;
和std::cout << S1 + S2<<std::endl;
都发生了报错
你一定会说,你没有重载 =哇! 可惜我重载了
String& String::operator= (String& source)
{
#ifdef DeBug
std::cout << "\ncall String& String::operator= (String& source)" << std::endl;
#endif // DeBug
if (&source == this)//本来就是自己
return *this;
lenght = 0;
delete[] chars;
chars = new char[source.lenght+1];
for (int i = 0; i < source.lenght; i++)
chars[i] = source.chars[i];
chars[source.lenght] = '\0';
lenght = source.lenght;
return *this;
}//重载等于 = 左值
按道理重载了=
上述语句应该没有错误的。这里涉及到左值和右值的问题
当然,我上学期学习c++的时候也遇到这类问题,请教老师,结果老师不理我,AHH,于是问题就留到了今天。
左值和右值
要弄明白右值引用到底是怎么一回事,必须要对左值和右值做一个明确的理解。
左值(lvalue, left value),顾名思义就是赋值符号左边的值。准确来说, 左值是表达式(不一定是赋值表达式)后依然存在的持久对象。
对左值和右值的一个最常见的误解是:等号左边的就是左值,等号右边的就是右值。
而 C++11 中为了引入强大的右值引用,将右值的概念进行了进一步的划分,分为:纯右值、将亡值。
纯右值(prvalue, pure rvalue),纯粹的右值,要么是纯粹的字面量,例如 10
, true
; 要么是求值结果相当于字面量或匿名临时对象,例如 1+2
。非引用返回的临时变量、运算表达式产生的临时变量、 原始字面量、Lambda 表达式都属于纯右值。
我们后续讨论 将亡值这种右值
左值和右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象,人家毕竟叫将亡值。
这样实在时太难理解了,还是来一点例子吧:
int a = 10;
int *p = &a;
int a=b+c;
a++;
++a;
请问 a, a++, p, &a, b+c 谁是右值。
我们这里又一个非常好判断的秘诀:无法取地址的变量是右值,右值是指表达式结束时就不再存在的临时对象(无法持久存在) ,所以取不了地址.
- a 可以取地址 ,左值
- &a 使用过之后就不存在了 ,无法取地址 ,右值
- p 左值
- b+c 无法取地址 ,右值
- a++ ,是先取出持久对象a的一份拷贝,再使持久对象a的值加1,最后返回那份拷贝,而那份拷贝是临时对象(不可以对其取地址),故其是右值;
- ++a,a则是使持久对象a的值加1,并返回那个持久对象a本身(可以对其取地址),故其是左值;
右引用
变量分左值和右值,那么引用也得分左右。
刚开始学习c++,书上就讲了左引用 . 也就常见 int&
,那么右引用如何表示呢?int&&
不要认为ta是对地址的引用哇QWQ.
所以回到刚开的问题,为啥哪里还会报错?当然就是我仅仅重载了 左值=
,所以再重载一个右值=
就解决了。
String& String::operator = (String&& source)
{
#ifdef DeBug
std::cout << "\ncall String& String::operator = (String&& source)" << std::endl;
#endif // DeBug
lenght = source.lenght;
chars = source.chars;
source.lenght = 0;
source.chars = nullptr;
return *this;
}//重载 =右值
结语
这本 电子版的 现代 C++ 教程: 高速上手 是非常不错的,希望自己能够精通C++ (doge)