C++ primer 第三章-Strings, Vectors, and Arrays

Hi!这里是山幺幺的c++ primer系列。写这个系列的初衷是,虽然在学校学习了c++,但总觉得对这门语言了解不深,因此我想来啃啃著名的c++ primer,并在这里同步记录我的学习笔记。由于我啃的是英文版,所以笔记是中英文夹杂的那种。另外由于已有一定的编程基础,所以这个系列不会含有太基础的知识,想入门的朋友最好自己啃书嘻嘻~

关于using声明


using std::cin;
using namespace std;
  • 头文件中不应含using声明,因为头文件中的内容会被复制到所有include它的文件中

关于string


声明

  • #include <string>
  • using std::string;

初始化

string s5 = "hiya"; // copy initialization
string s6("hiya"); // direct initialization
string s7(10, 'c'); // direct initialization; s7 is cccccccccc
string s8 = string(10, 'c'); // copy initialization; s8 is cccccccccc
//等价于
string temp(10, 'c'); // temp is cccccccccc
string s8 = temp; // copy temp into s8

操作

  • 上图第二行:whitespace(包括空格、tab、换行等)-separated是指 cin >> s1 >> s2; 输入“ Hello World ”会让s1=Hello,s2=World
  • 上图第三行:可以用 while (getline(cin, line)) 读文件,line不包含换行符
  • 上图第五行:返回类型是string::size_type,是一个unsigned且足够容纳任何string的类型【所以当n是负数时,s.size() < n会返回true,因为n会转换为一个signed且值较大的数】
  • 上图第七行:字符串字面量并不是string类型
string s5 = "hello" + ", "; // error: no string operand
string s6 = s1 + ", " + "world"; // ok: each + has a string operand
string s7 = "hello" + ", " + s2; // error: can't add string literals

#include <cctype>

PS:cctype是从c的ctype.h中迁移过来的

index(s[i])

  • if our index has a signed type, its value will be converted to the unsigned type that string::size_type represents

关于vector


声明

  • #include <vector>
  • using std::vector;

vector的性质

  • vector是template而不是type,实例化的vector才是type
  • 引用不是对象,所以无法把vector实例化为引用
  • we can (efficiently) add elements to a vector at run time

初始化

  • 上图第五行:要求T是有默认初始值的类型,比如int(0)、string("")等
  • list initialization
vector<string> v5{"hi"}; // list initialization: v5 has one element
vector<string> v6("hi"); // error: can't construct a vector from a string
literal
vector<string> v7{10}; // not a list initialization: v7 has ten default-initialized elements
vector<string> v8{10, "hi"}; // not a list initialization: v8 has ten elements with value "hi"

操作

  • 上图第三行:注意for循环体内语句不能改变the size of the sequence over which it is iterating.
  • 上图第二行:若是一个int型vector,则返回类型为vector<int>::size_type

关于迭代器


基本性质

  • iterators give us indirect access to an object
  • 迭代器指向的对象是:容器中的元素或者string中的char
  • 若容器v是空的,则v.begin() == v.end()
  • 任何改变容器大小的操作都可能使迭代器失效

操作

  • 第一行:有时括号是必要的:
(*it).empty() // ok
*it.empty() // error: attempts to fetch the member named empty from it

类型

vector<int>::iterator it; // it can read and write vector<int> elements
string::iterator it2; // it2 can read and write characters in a string
vector<int>::const_iterator it3; // it3 can read but not write elements
string::const_iterator it4; // it4 can read but not write characters
auto it3 = v.cbegin(); // it3 has type vector<int>::const_iterator

string、vector迭代器支持的运算

  • 第五行:返回类型是difference_type,是一个signed
  • 栗子
auto mid = vi.begin() + vi.size() / 2;
if (it < mid) ...

关于array


基本性质

  • 大小固定,不能增加元素
  • 因为引用不是对象,所以没有元素是引用的array

初始化

unsigned cnt = 42; // not a constant expression
constexpr unsigned sz = 42; // constant expression
int arr[10]; // array of ten ints
int *parr[sz]; // array of 42 pointers to int
string bad[cnt]; // error: cnt is not a constant expression
string strs[get_size()]; // ok if get_size is constexpr, error otherwise

int a2[] = {0, 1, 2}; // an array of dimension 3
int a3[5] = {0, 1, 2}; // equivalent to a3[] = {0, 1, 2, 0, 0}
string a4[3] = {"hi", "bye"}; // same as a4[] = {"hi", "bye", ""}
int a5[2] = {0,1,2}; // error: too many initializers

char a1[] = {'C', '+', '+'}; // list initialization, no null
char a2[] = {'C', '+', '+', '\0'}; // list initialization, explicit null
char a3[] = "C++"; // null terminator added automatically

int a[] = {0, 1, 2}; // array of three ints
int a2[] = a; // error: cannot initialize one array with another
a2 = a; // error: cannot assign one array to another

PS:若array没有定义在任何函数内,则未初始化的array中的元素初始值为undefined;否则有默认初始值(比如,int初始值为0,string初始值为"")

*和&

int *ptrs[10]; // ptrs is an array of ten pointers to int
int (*Parray)[10] = &arr; // Parray points to an array of ten ints
int (&arrRef)[10] = arr; // arrRef refers to an array of ten ints
int *(&arry)[10] = ptrs; // arry is a reference to an array of ten pointers
  • 第一行:从左往右读,int*表示这个array存放的元素是指向int的指针
  • 第二行:先读括号,*Parray表示Parray是一个指针
  • 第三行:先读括号,&arrRef表示arrRef是一个引用

index

  • 可以把用作index的变量i定义为 size_t 类型,它定义在头文件cstddef中,也就是stddef.h的c++版本
  • size_t 是一个unsigned类型,large enough to hold the size of any object in memory
  • index也可以是负数:The library types force the index used with a subscript to be an unsigned value. The built-in subscript operator does not. The index used with the built-in subscript operator can be a negative value.
int *p = &ia[2]; // p points to the element indexed by 2
int j = p[1]; // p[1] is equivalent to *(p + 1),
// p[1] is the same element as ia[3]
int k = p[-2]; // p[-2] is the same element as ia[0]
int k = p[-3]; // error: out of range

array名是指针

int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia is an array of ten ints
auto ia2(ia); // ia2 is an int* that points to the first element in ia
// 但使用decltype时会变成array类型
decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};

迭代器

int arr[] = {0,1,2,3,4,5,6,7,8,9};
// 类似于begin()
int *p = arr; // p points to the first element in arr
++p; // p points to arr[1]
// 类似于end()
int *e = &arr[10]; // pointer just past the last element in arr
// 以下在iterator头文件中
int *beg = begin(arr); // pointer to the first element in ia
int *last = end(arr); // pointer one past the last element in ia

指针运算

auto n = end(arr) - begin(arr); // n is 5, the number of elements in arr
  • n的类型是 ptrdiff_t ,是一个signed,定义在头文件cstddef中
  • 指向同一array内元素的指针可以比较大小

关于C风格的字符串(最好别用!)


基本性质

  • 以'\0'结尾
char ca[] = {'C', '+', '+'}; // not null terminated
cout << strlen(ca) << endl; // disaster: ca isn't null terminated

操作

  • 以下函数均定义在头文件cstring中

用array初始化vector


int int_arr[] = {0, 1, 2, 3, 4, 5};
vector<int> ivec(begin(int_arr), end(int_arr));
// copies three elements: int_arr[1], int_arr[2], int_arr[3]
vector<int> subVec(int_arr + 1, int_arr + 4);

关于多维array:即array的array


初始化

int arr[10][20][30] = {0}; // initialize all elements to 0

int ia[3][4] = { // three elements; each element is an array of size 4
{0, 1, 2, 3}, // initializers for the row indexed by 0
{4, 5, 6, 7}, // initializers for the row indexed by 1
{8, 9, 10, 11} // initializers for the row indexed by 2
};
// equivalent initialization without the optional nested braces for each row
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
// explicitly initialize only element 0 in each row
int ia[3][4] = {{ 0 }, { 4 }, { 8 }};
// explicitly initialize row 0; the remaining elements are value initialized
int ix[3][4] = {0, 3, 6, 9};

index

int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
int (&row)[4] = ia[1]; // binds row to the second four-element array in ia

遍历

for (auto &row : ia) {
  for (auto &col : row) ...
}

for (const auto &row : ia) { // 即使不需要写,也要用引用,否则row的类型会推断为指向ia每行第一个元素的int*
  for (auto col : row) ...
}

for (auto p = ia; p != ia + 3; ++p) {
  for (auto q = *p; q != *p + 4; ++q) ...
}

for (auto p = begin(ia); p != end(ia); ++p) {
  for (auto q = begin(*p); q != end(*p); ++q) ...
}

指针相关

int ia[3][4]; // array of size 3; each element is an array of ints of size 4
int (*p)[4] = ia; // p points to an array of four ints
p = &ia[2]; // p now points to the last element in ia
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容