本文是深蓝学院C++课程的课堂笔记。
初始化基本操作:
Struct Str
{
// 8000~8001
char b;
// 对齐信息:8002这个位置不能对齐int类型(4 byte),所以从8004开始
// 8004~8007
int x;
}
“Hello” -> char[6]
因为字符串最后一个字符是“\0”
缺省值
拷贝初始化
直接初始化
指针:
地址 0x5678 -> 地址 0x1234
内容 0x1234 -> 内容4
指针特点:
可以指向不同类型
尺寸相同
int* p1 = &x;
char* p2 = &y;
sizeof(p1) = 8
sizeof(p2) = 8
为什么尺寸相同呢?
为什么指针需要指明目标的类型呢?
指针有缺省值吗?
有2种缺省情况:
不知道初始值是多少的指针,怎么初始化呢?
赋地址0x0000,简单来说就是: int* p = 0;
这样肯定会报错,因为系统不允许访问0x0000地址。但只要我们后面赋值了,代码run了,就说明指针很鲁棒。
上面的初始化int* p = 0
其实是有潜在风险的:
如果系统函数能够重载,那么0这个type它会默认选择最match的一种重载函数:
void fun(int)
{}
void fun(int *)
{}
fun(0);
int* p = 0;
fun(p)
int* p = nullptr;
fun(p);
if(p) // 也即,if(p != nullptr)
{}
else
{}
指针的解引用,增加,减少
指针p和指针p+1的地址相差为这个指针类型的size,而不是地址+1。
void*
指针
指针 vs 对象
int& age = 1
或者int& age = &1
都是不对滴~int** pp = p
(正确)int& & ref2 = ref1
(错误)const是编译器概念,编译器用它来:
const int x =4;
// ....
int y = x + 1;
const 指针分为两种类型:
int* const ptr = &x;
ptr = &y;
(错误,因为ptr里面存储的内容是不能改变的,只可以指向&x)const int* ptr = &x;
*ptr = 3;
(错误,因为ptr指向的地址的内容是不能改变的,但可以改变ptr指向其他地址)const 引用:
const 引用 vs const指针:
fun(nullptr);
const int& param = 3
,使用字面值来赋值。这是C++标准为了函数传参能够直接用字面值进行赋值,而专门网开一面
。而如果不是const 引用,是不可以int& param = 3
,这样没有const是不能用字面值给引用的。constexpr 常量表达式 (c++ 11)
typedef int MyInt;
或
using MyInt = int;
int x = 3.5 + 18l;
-->
auto x = 3.5 + 18l;
问题:auto可以推测类型,但是有可能类型会产生退化
int n = 10;
int& ref = n;
auto ref_auto = ref;
//此时ref_auto的类型是int,发生了类型退化!
解决:
//推导出引用类型,并且避免类型退化
auto& ref_auto = ref;
decltype(exp)
: 返回exp的类型,左值加引用
decltype(val)
: 返回val的类型
decltype(auto)
: (c++14开始支持)既不会发生类型退化,也不用写一大堆(直接用auto代替)
concept auto
: (c++20开始支持)可以限制auto推导类型的范围,比如std::integral auto x = 3.5;
就会报错,因为限制在了std::integral
类型范围内,而3.5是一个double
。
//例子
int x = 3;
int* ptr = &x;
decltype(x); // val --> int
decltype(*ptr); // exp --> int& (*ptr是一个expression,而不是value啦,所以左值加引用)