C/C++ 关于左右值的问题

以前记得学过,后来又忘了,现在做一个总结;

一、左右值基本定义:

简而言之,左值就是指那些拥有地址,在存储单元内存储数值的变量,可以通过变量名去访问;

而右值这事中间的临时变量,无法通过地址进行访问,表达式或者生存周期结束之后就被彻底销毁;

这里右值还分为两种:

1.纯右值:非引用返回的临时变量( int func(void) )、运算表达式产生的临时变量(b+c)、原始字面量(2)、lambda表达式等;

2.将亡值:将要被移动的对象、T&&函数返回值、std::move返回值和转换为T&&的类型的转换函数的返回值;

因此可以看到,右值无法通过传统的变量进行访问或者赋值;

二、左值引用和右值引用:

左右值也可以通过引用来进行访问;

1.左值引用:

左值引用比较熟悉,就是一个变量的别名而已,不开辟其他空间;

但是左值引用既可以引用左值,也可以引用右值;

例如对于典型的函数传参 const type&,就可以直接接受右值;

int &a = 2;       // 非常量左值引用 绑定到 右值,编译失败
 
int b = 2;        // b 是非常量左值
const int &c = b; // 常量左值引用 绑定到 非常量左值,编译通过
 
const int d = 2;  // d 是常量左值
const int &e = d; // 常量左值引用 绑定到 常量左值,编译通过
const int &f =2;  // 常量左值引用 绑定到 右值,编译通过

2.右值引用:

右值引用可以通过接受一个右值,使其延长生存周期,只要该变量存在,临时右值就不会被销毁;

右值引用一般接收右值或者move后的左值(也就是直接将左值数据夺取后的右值);

int a;
int &&r1 = a;             // 编译失败
int &&r2 = std::move(a);  // 编译通过

值得注意的是,关于右值引用变量类型是右值引用,但是其变量是左值,这点在Modern Effective C++条款一有提到过;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设二叉排序树的二叉链表存储结构的类型定义如下: typedef struct node{ int data; //用整数表示一个结点的名 struct node *LChild,*RChild; //左右指针域 }BSTNode,*BSTree; 设计算法并编写程序求解以下几个问题。 8 12 14 10 7 3 15 6 2 4 1 5 11 9 13 16 13 (1)键盘输入一个元素序列创建一棵二叉排序树,输出该二叉排序树的中序遍历序列; 例如,若输入 45,24,55,12,37,53,60,23,40,70 则创建的二叉排序树为: 输出结果为:12 23 24 37 40 45 53 55 60 70 (2)在(1)中所得的二叉排序树中插入一个为 58 的结点,再输出它的中序遍历序列,输出 结果为:12 23 24 37 40 45 53 55 58 60 70 (3)在(1)中所得的二叉排序树中删除为 45 的结点,再输出它的中序遍历序列,输出结果 为:12 23 24 37 40 53 55 58 60 70 (4)利用(1)中所得的二叉排序树的所有叶子结点构造一个带头结点的单链表 L。要求不能 破坏这棵二叉排序树。所得的单链表 L 如下。 输出该链表各结点的,输出结果为:23 40 53 70 (5)设计算法将(1)中所得的二叉排序树的左右子树进行交换,由于二叉树是一种递归定义, 所以子树的左右两棵子树也要相交换,依此类推。最后输出所得到的二叉树的中序遍历序列。 例如,经过上述操作后,(1)中所得的二叉排序树变为如下形式。 输出该二叉树的中序序列,结果为:70 60 55 53 45 40 37 24 23 12 (6)设计算法统计并输出(1)中所得的二叉排序树中只有一个孩子结点的结点个数。输出结 果为:3(7)在(1)中所得的二叉排序树中,设计算法并编写程序输出结点 40 的所有祖先结点。输 出结果为:45 24 37
C语言的线段树可以使用数组来实现,每个节点表示一个区间。以下是一个基本的线段树结构体及其相关函数的示例代码: ```c const int MAXN = 100005; // 区间长度的最大 struct SegTreeNode { int l, r; // 区间左右端点 int sum; // 区间内元素的和(这里以求和为例) // 构造函数 SegTreeNode() : l(0), r(0), sum(0) {} // 复制构造函数 SegTreeNode(const SegTreeNode& o) : l(o.l), r(o.r), sum(o.sum) {} }; SegTreeNode segTree[MAXN << 2]; // 线段树数组,使用区间长度的4倍大小 // 建立线段树(输入数组为a,当前节点为i,区间为[l, r]) void build(int i, int l, int r, int a[]) { segTree[i].l = l; segTree[i].r = r; if (l == r) { segTree[i].sum = a[l]; return; } int mid = (l + r) >> 1; build(i << 1, l, mid, a); build(i << 1 | 1, mid + 1, r, a); segTree[i].sum = segTree[i << 1].sum + segTree[i << 1 | 1].sum; } // 区间查询(查询区间[qL, qR]的和,当前节点为i) int query(int i, int qL, int qR) { if (segTree[i].l >= qL && segTree[i].r <= qR) { return segTree[i].sum; } int mid = (segTree[i].l + segTree[i].r) >> 1; int res = 0; if (qL <= mid) { res += query(i << 1, qL, qR); } if (qR > mid) { res += query(i << 1 | 1, qL, qR); } return res; } // 区间修改(将区间[pL, pR]加上x,当前节点为i) void modify(int i, int pL, int pR, int x) { if (segTree[i].l >= pL && segTree[i].r <= pR) { segTree[i].sum += x; return; } int mid = (segTree[i].l + segTree[i].r) >> 1; if (pL <= mid) { modify(i << 1, pL, pR, x); } if (pR > mid) { modify(i << 1 | 1, pL, pR, x); } segTree[i].sum = segTree[i << 1].sum + segTree[i << 1 | 1].sum; } ``` 使用示例: ```c #include <stdio.h> int main() { int n = 10; int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 建立线段树 build

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值