[深蓝学院] C++ Week 3: 数组

[深蓝学院] C++ Week 3: 数组, Vector, 字符串

  • 1. 数组
    • 1.1 数组初始化
      • 1.1.1 可变长度的数组?
      • 1.1.2 缺省值
      • 1.1.3 聚合初始化
      • 1.1.4 不能用auto来声明数组类型
      • 1.1.5 数组不能复制
      • 1.1.6 字符串的初始化
    • 1.2 数组的复杂声明
      • 1.2.1 指针的数组 和 数组的指针
      • 1.2.2 声明数组的引用
    • 1.3 数组的元素访问
      • 1.3.1 左值和右值
      • 1.3.2 转换成指针类型
      • 1.3.3 x[y] -> * ((x)+(y))
    • 1.4 从数组到指针
      • 1.4.1 数组和指针的隐式转换
    • 1.5 数组的其他操作
      • 1.5.1 数组所含元素的个数
      • 1.5.2 遍历数组元素
    • 1.6 C字符串
    • 1.7 多维数组
  • 2. Vector
    • 2.1 Vector的易用性
    • 2.2 Vector的初始化
    • 2.3 Vector的方法
    • 2.4 多维Vector
  • 3. String

本文是深蓝学院c++课程的个人笔记和感悟,仅供学习参考。

1. 数组

1.1 数组初始化

1.1.1 可变长度的数组?

  • c++里面数组的初始化一般来说必须给定一个确切的大小,比如int b[3]
  • 如果用variable length的数组,比如int b[x],原则上是不可以的。
    因为系统在编译(compile)的时候没办法知道x这个变量是多少,那就没办法分配内存空间; 只有在运行(run)的时候才可能知道x是多少。

1.1.2 缺省值

  • 在main函数里面的缺省值是随机的。
  • 在main函数外面的全局定义的数组,则全部初始为0。
#include 

int b[3];
int main() {
    int a[3];

    std::cout << a[0] << std::endl;
    std::cout << b[0] << std::endl;

    return 0;
}

---result----
a[0]: 21919 (random)
b[0]: 0

1.1.3 聚合初始化

  • 如果3个长度的数组,只给它2个数值: int a[3] = {1,2}。那么a[3]自动初始化为0

1.1.4 不能用auto来声明数组类型

auto a = {1,2,3}中a的类型其实是std::initializer_list[3]

1.1.5 数组不能复制

c++不支持数组直接复制:

int a[] = {1,2,3}
int b = a; // X,错误!

问:为神马c++不支持数组的复制呢?
答:因为c++是一种注重性能的语言,复制得开辟好多空间喔~

1.1.6 字符串的初始化

char str[] = "hello" // char[6]
char str[] = "h", "e", "l", "l", "o" // char[5]

神奇!为神马第二种方式的str变量变成char[5],而第一个是char[6]呢?
原因: c/c++会在第一种初始化的字符串后面“偷偷地”加一个'\0'字符,用来判断字符串的结束。

1.2 数组的复杂声明

1.2.1 指针的数组 和 数组的指针

int* data[3] = {&x1, &x2, &x3}; //data是一个包含三个int*指针的数组
int (*data)[3] = {x1, x2, x3};  //data是一个int[3]数组的指针

1.2.2 声明数组的引用

int (&data)[3] = {x1, x2, x3}

1.3 数组的元素访问

1.3.1 左值和右值

数组对象是一个左值

1.3.2 转换成指针类型

1.3.3 x[y] -> * ((x)+(y))

  • a[1]其实等于1[a]: *((1)+(a))
  • 如果超出界限,就会出现内存访问越界,但是非常非常危险,因为会访问到越界的那个地址上的数据,而不会像python给你报错。

1.4 从数组到指针

1.4.1 数组和指针的隐式转换

[深蓝学院] C++ Week 3: 数组_第1张图片

  • 数组和指针如果用auto,是会发生隐式转换的。本来右边是个数组,auto之后就变成指针了。因为a[1] = *((1)+(a)),数组其实也是需要基于地址的访问。
  • 但是,数组和指针的内存结构其实非常不同,如上图所示:
    • 数组保存的直接就是数据内容
    • 指针保存的是指向的地址
  • extern int array[]用extern的时候一定不能用指针哈,不然会把array前8个字节的数据(而且根据高位低位的规则,后4位放在前面)当成指针指向的地址… 完全跑飞了
  • std::cbegin(array)
  • std::cend(array)这里的c是指const,防止不小心更内容。

1.5 数组的其他操作

1.5.1 数组所含元素的个数

  • sizeof(array) / sizeof(int)
  • std::size()
  • std::cbegin() and std::cend()

但对于std::vector来说,sizeof(vector)只能返回一个固定值24(根据编译器而定)。因为std::vector通常由三个8 byte的Pointer(指针)组成:

  • begin of vector
  • end of vector
  • end of reserved memory for vector (i.e. vector’s capacity)

1.5.2 遍历数组元素

  • 基于元素个数
    for(int i; i
  • 基于pointer
auto ptr = std::cbegin(a)
while(ptr != std::cend(a))
{
   ptr = ptr + 1;
}
  • 基于range-based for循环
for(int x: a){
	std::cout << x << std::endl;
}

1.6 C字符串

c字符串用strlen可以求出长度,但是一定要注意,在单个定义字符串的字符时,最后结尾要加一个\0来结尾。不然其实程序是pointer一直在内存里面找下一个字符,直到找到\0才会截止。

include <cstring>

char str1[] = "Hello";
char str2[] = ['H', 'e', 'l', 'l', 'o', '\0'];
auto ptr = str1;
std::cout << strlen(str1) << std::endl;
std::cout << strlen(str2) << std::endl;
std::cout << strlen(ptr) << std::endl;

1.7 多维数组

//一重大括号 vs 多重大括号
int x2[3][4] = {1,2,3,4,5,6};
int x2[3][4] = {{1,2,3,4}, {5,6}};
// (int, int, int, int), (int, int, int, int), (int, int, int, int)

// 自动补0
int x3[][3] = {1,2,3,4}
// 系统会直接给补全,初始化为X3[2][3]

int x4[][4] = {{1,2,3}, {5,6,7,8}}
// 自动会把第一排最后一个补0,{1,2,3,0}

2. Vector

2.1 Vector的易用性

  1. Vector可以复制,但Array不可以
  2. Vector可以在运行期改变元素个数,但Array不可以

相比之下,内建数组更加注重性能。

2.2 Vector的初始化

std::vector<int> a(3,1); //3个元素,每一个的数值都是1
std::vector<int> a{3,1};
std::vector<int> a = {1,2,3,4};
// {1,2,3} 表示一个std::initializer_list 初始化列表

2.3 Vector的方法

std::vector<int> x1;

// Vector的基本方法
x1.size()
x1.empty()
x1.push_back(val)
x1.pop_back()

// Vector的比较
x1 == x2
x1 < x2 // Vector的比较是按照priority来: 
		// 先看第一位是不是相同,如果不同,那直接就用第一位的结果作为最终大小比较的结果啦!

// Vector中元素的遍历
x1[index]
x1.at(index) // 建议使用vec.at(idx),因为这样如果idx>size,系统会报错。

// 指针访问Vector
std::vector<int>* ptr = &x1;

// 指针访问Vector所包含的Method: -> 以及 .
(*ptr).size()
ptr->size()

2.4 多维Vector

int a[3][4];
//Array的a[0]和a[1]的维度都是一样的

std::vector<std::vector<int>> vec = {{1,2,3}, {4,5}};
//Vector可以不同维度的元素长度是可以不一样的

3. String

std::string x("Hello String");
std::string y("Hello");

y = y + "Wei";
//std::string是可以支持拼接的,但是内建字符串char[]是不能拼接的。

你可能感兴趣的:(c++,c++,指针,数组)