左右值与高低位DC

 

 

 
区分左值/右值”是为了让语言、库、编译器能够知道对象之后是否还会被用到,从而决定是搬资源(move)还是复制资源(copy),最终目标只有两个:性能与资源
 
void f(T); // copy
void f(const T&);  // 拷贝, copy
f(T&&);       // 移动, move
 
 

1. 1 术语解释

 
左值(lvalue)——有身份、有持久地址; 右值(rvalue)——没身份、只剩值。
能取地址的叫左值,不能的叫右值;std::move 把左值“变成”右值,同时将参数置空;
表达式示例 值类别 典型特征
int x = 0; 中的 x 左值lvalue 有名字、可取地址、生命周期长
std::string("tmp") 纯右值prvalue 临时对象、无名字、不可取地址
std::move(x) 将亡值xvalue 仍是 x 的别名,但被强制右值化
arr[3] 左值lvalue 返回的是具体元素,有地址
x + y 纯右值prvalue 结果是临时值,无持久地址
prvalue和xvalue都是rvalue
 
 
维度 拷贝构造 T(const T&) 移动构造 T(T&&)
形参类别 const 左值引用 右值引用
语义 复制 搬家
源对象状态 保持不变 被搬空(合法但未定义)
是否分配新资源 通常要 通常不(只移交指针)
运行期代价 O(n) 或更大 O(1)
典型触发场景 T b = a; T b = std::move(a); 或返回局部变量
若类成员有 const 成员 仍可合成 禁止合成(const 不能“搬家”)
 
对于100万个元素的容器
维度 移动构造 拷贝构造
新内存申请 ❌ 无 ✅ 重新 new 一块
元素复制 ❌ 无 ✅ memcpy 100 万次
原对象 a 被搬空(指针置空) 保持不变
运行期代价 O(1) 只复制 3 个指针 O(N) 复制 100 万个元素
 
std::vector<int> a;
 
std::vector<int> c(std::move(a))的伪代码逻辑:
  1. 将对象的的地址进行赋值(复制 3 个指针,不是元素指针);
// 移动构造的伪代码
c.begin_ = a.begin_;   
c.end_   = a.end_;     
c.cap_   = a.cap_;     

a.begin_ = a.end_ = a.cap_ = nullptr;
 
 
std::vector<int> c(a)拷贝构造的伪代码
  1. 重新申请资源
  2. 对数据进行复制(重复N次)
  3. 将对象的的地址进行赋值;
// 拷贝构造的伪代码
T* src = &a;
T* ptr = new T[N]
for(int i = 0; i < N; ++i)
    memcpy(ptr, src, sizeof(N));


c.begin_ = ptr;   
c.end_   = ptr + N;     
c.cap_   = ptr + N;     
 
 

2. 功能范围

 
场景 std::move std::forword
触发移动语义 ✅ 用于将左值转为右值,调用移动构造/赋值 ❌ 不直接用于触发移动
完美转发参数 ❌ 会强制转为右值,破坏原始值类别 ✅ 保持参数的原始值类别
模板函数 ❌ 不适用于转发 ✅ 用于万能引用参数转发
返回值优化 ✅ 用于返回局部变量 ❌ 不用于返回值
 

3. 影响

 
X: 副本复制,深度构造;
const X&:只读绑定,变量别名;需要保证变量的声明周期
X&&:移动构造
 
 
只对原数据进行操作,使用左值引用 (X&)
数值传递(值和生命期),使用右值引用(X&&)
 
 
 
 
对于0x12345678的数据,高位是0x12, 低位是0x78
大端:高位字节放到低地址
小端:高位字节放到高地址
地址 uint8 a[4] 大端存储 小端存储
0x1000 a[0] 0x12(最高位) 0x78(最低位)
0x1001 a[1] 0x34 0x56
0x1002 a[2] 0x56 0x34
0x1003 a[3] 0x78(最低位) 0x12(最高位)
posted @ 2025-08-25 15:57  sciapex  阅读(15)  评论(0)    收藏  举报