本 Wiki 开启了 HTTPS。但由于同 IP 的 Blog 也开启了 HTTPS,因此本站必须要支持 SNI 的浏览器才能浏览。为了兼容一部分浏览器,本站保留了 HTTP 作为兼容。如果您的浏览器支持 SNI,请尽量通过 HTTPS 访问本站,谢谢!
这是本文档旧的修订版!
第 4 章笔记
int x = 0;
// C++ 没有规定此类的表达式的顺序
// complier depended
func(x = x + 1; x = x + 1) ;
// 对 x 的评估结果是获得 x 关联的内存位置
x = 3;
x = 3; // used for init
3 + 2; // used as operands
// temp objects is pvalue
int{};
std::vector<int> x;
// 调用右值引用
void fun(std::vector<int>&& par)
// x 被转变为了亡值, x 对应的 vector 资源已经被转交
fun(std::move(x));
gvalue
:就是标识了一个一个对象,位或者函数xvalue
:并不是即将消除的值prvalue
=
的左右没有特定的关系
// x 是左值
const int x = 3;
// error, x 不能放到 = 左边
// x 是 immutiable value
x = 3;
// 右值可以放到 = 左边
struct Str {};
int main()
{
// Str() 是临时变量,是右值
Str() = str();
}
//x, y 是左值
int x = 3;
int y = 3;
// + 需要右值作为 operand,此时传入的是左值
// 左值在这里就转变为了右值
// l to r conversion
x + y
struct Str
{
int x;
}
int main()
{
// prvalue temp object
Str();
// 从 Str() 临时对象中取出 x 代表的数据
// 这个过程中,取值过程将 Str() 代表的临时对象转变了有标识的值
// 所以 Str() 标识了一个位置,但又即将消亡
// 也就是 prvalue 到 gvalue 转变
Str().x;
}
void fun(const int& par) {}
int main()
{
//3 从 rvalue 转换为 xvalue
fun(3);
}
xvalue
返回 T&&lvalue
返回 T&prvalue
返回 T
int main()
{
int x;
// y 是 int 类型,x 是实体
decltype(x) y;
// z 是 int& 类型, (x) 是表达式
decltype((x)) z;
// w 是 int&&
decltype(std::move(x)) w = std::move(x);
}
entity: unparenthesized id-expression or an unparenthesized class member access expression.
Reference: Implicit conversions
// 数值提升:低精度自动到高精度
// 整型提升:e.g. int to float
3 + 0.5;
// 浮点型提升:e.g. float to double
// 数值转换
// 不是所有的类型都能进行隐式转换
// error, 字符串不能转换为 double
"abc" + 0.5;
,
显式转换的意义:处理隐式转换无法处理的场景:
int x = 3;
int y = 4;
// 使用显式转换得到浮点数结果
// x 被隐式转换(左值->右值->double),y 被显式转换
std::cout << (x / static_cast<double>(y));
static_cast<>()
:() 中是被转换的值,<> 中是需要被转换的类型
// 显式的将数值从 int 转化为 double
static+cast<double>(3) + 0.5;
类型转换有局限性,不是所有类型都可以互转,无论是显性还是隐性
void
类型的指针转换为任意类型的指针(这种转换不被隐式转换支持)const_cast<>()
:转换当前表达式的 const
int x = 3;
const int& ref = x;
// ref2 是 non-const 的引用
int& ref2 = const_cast<int&>(ref);
注意:如果是绑定常量的引用,请不要使用 const_cast 改变其常量性。编译器对常量经常会进行编译优化,这往往是基于编译器来进行的。这种行为是 undefined 的,非常危险。
reinterpret_cast<>()
:将当前类型重新解释为另外一种类型(将当前内存空间以另外一种形式来解释)
int x = 3;
int *ptr = &x;
// 强行解释 int 到 double, 通过指针
// 指针转换后,会以 double 的方式解引用当前的 int
// 由于 double 需要 8 位, int 4 位,则解引用会将后 4 位的内存内容与前四位合并,并解引用
double * ptr2 = reinterpret_cast<double>(ptr);
c-style 转换会以特定的执行顺序执行 C++ cast 来进行转换。该转换过程是由编译器通过尝试得出的,并不完全可控。最好的方式是避免在 C++ 中使用诸如此类风格的转换。
// 不推荐在 C++ 中使用
int x = 3;
(double)x;
C++ 希望用户尽量少使用显性的类型转换(名字又臭又长)。
+
),负(-
)(一元)
// rvalue
3 + 5
// lvalue->rvalue->rvalue
int x = 3;
int y = 5;
x + y
// y 是 int 类型
short x = 3;
auto y = +x;
// 1
4 / 3
// - 1
-4 / 3
m%n
时,m
与 m%n
的结果同号a>b>c
)⇔
(C++ 20)std::strong_ordering
:包含了一些关系相关的常量(比如 std::strong_odering::less
,包含相等和等价)std::weak_ordering
:不包含相等关系(用于只能说等价,不能说相等的数据结构,)std::partial_ordering
:还包含了一种 unordered 的关系。0
,因此是一种等价但无法区别的关系NaN
(not a number),任意数与其比较都会返回 partial ordering 的关系。