C++ 学习笔记(3)命名空间using、字符串、string、vector、迭代器、数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l773575310/article/details/79008646

C++ 学习笔记(3)命名空间using、字符串、string、vector、迭代器、数组

参考书籍:《C++ Primer 5th》


3.1 命名空间的using声明

  • 头文件不应该包含using声明:如果有,那么每个使用了该头文件的文件都会有这个声明,容易造成冲突。

3.2 标准库类型string

3.2.1 定义和初始化string对象

  • 直接初始化:使用构造函数。
  • 拷贝初始化:使用赋值符号(=)。

3.2.2 string对象上的操作

  • 头文件:。在标准命名空间std下。

  • 读操作时,string对象会自动忽略开头的空白(空格符、换行符、制表符),从第一个正在字符读起,知道遇到下一处空白为止。

    • 使用std::getline()读取一行:直到遇到换行符为止(换行符也读进去了),然后把内如存入string对象中去(换行符不存)。
std::string line;                       // 字符串
while (getline(std::cin, line))         // 每次读一行,直到文件末端
    std::cout<< line << std::endl;      // 输出。endl:结束当前行并刷新显示缓冲区
  • string::size_type:无符号类型。string::size()的返回值,如果用了这个函数,就不要再使用int,避免混用 int 和 unsigned 可能带来的问题。

3.2.3 处理string对象中的字符

  • 使用for循环处理每个字符,如果要修改字符需要把循环变量定义为引用类型。
for (auto &c : s)       // 遍历字符串s,每个字符c的引用
    c = toupper(c); // 将所有字符转换到大写

3.3 标准库类型vector

3.3.1 定义和初始化vector对象

  • 列表初始化:如果确认无法执行列表初始化,编译器会尝试使用默认值初始化vector对象。
vector<int> v1(10);             // 10个元素,都为0
vector<int> v2{ 10 };           // 1个元素,为10

vector<int> v3(10, 1);          // 10个元素,都为1
vector<int> v4{ 10, 1 };        // 2个元素,为10和1

vector<string> v5("hi");        // 错误!不能使用字符串字面量初始化
vector<string> v6{ "hi" };      // 1个元素,为“hi”

vector<string> v7{ 10 };        // 有10个默认初始化元素(无法使用列表初始化,编译器尝试使用默认值,下同。)
vector<string> v8{ 10, "hi" };  // 有10个值为“hi”的元素

3.3.3 其他vector操作


3.4 迭代器介绍

3.4.1 使用迭代器

  • 使用了迭代器的循环体,都不要向迭代器所属容器添加元素(会使迭代器失效)。
  • 迭代器都拥有begin和end成员。end表示容器“尾元素的下一个位置(one past the end)”的迭代器,也称尾后迭代器(off-the-end iterator)。如果容器为空,begin和end放回的是同一个迭代器。

  • 如果vector或string对象是一个常量,只能使用const iterator。

3.4.2 迭代器运算

  • 两个迭代器相减得到的距离:difference_type 的带符号整形数。

3.5 数组

3.5.1 定义和初始化内置数组

unsigend cnt = 42;              // 非常量表达式
constexpr unsigned sz = 42;     // 常量表达式

int arr[10];                        // 含有10个数的数组
int *pass[sz];                      // 含有42个整形指针的数组

string bad[cnt];                    // 错误:cnt不是常量
string strs[get_size()];            // 当get_size()为constexpr时正确,否则错误

const int& a = 10;              // 常引用,还是变量
int b[a];                           // 错误:a还是变量
  • 数组的元素应为对象,不存在引用的数组。
  • 字符数组的结尾包含一个空字符,需要占用字节的。
int *prts[10];                  // 含有10个整形指针
int &refs[10];                  // 错误:不存在引用的数组
int (*parray)[10] = &arr;           // 指针,指向数组
int (&arrRef)[10] = arr;            // 引用,数组的引用
int *(&arry)[10] = ptrs;            // 数组的引用,该数组含有10个整形指针

3.5.3 指针和数组

  • 使用数组的时候,编译器一般会把它转换成指针。
  • 在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。
int nums[] = {1, 2, 3}; 
int *p1 = &nums[0];     // 指针指向nums的第一个元素
int *p2 = nums;         // 同上。

auto p3(nums);          // p3 的类型是整形指针。

decltype(nums) arr;     // arr 的类型是整形数组。

int ia[] = { 1,2,3,4 };
int *beg = begin(ia);       // 使用std::begin(),来获取数组的迭代器。
int *last = end(ia);
  • 两个指针相减表示距离。名为ptrdiff_t的有符号标准库类型。
  • 数组的下标,可以是负值。 vector、string下标为无符号类型(size_type)。

3.5.4 C风格字符串

  • 一般不负责验证其字符串参数(如:字符串没有以空字符结尾,一些函数使用会报错)。

  • 两个C风格字符串上,实际比较的是指针而非字符串本身。(string类型有重载比较符)。

3.5.5 与旧代码的接口

  • string::c_str(),将string返回一个C风格字符串,类型是const char *。
  • 无法保证c_str函数返回的数组一直有效,如果改变了调用的string对象,会让之前返回的数组失效。想保持原来的数组,可以重新拷贝一份。

3.6 多维数组

int a[3][4] = { {0},{1},{2} };  // 显示初始化每行第一个元素(第一列)
int b[3][4] = { 1,3,5,6 };      // 显示初始化第一行元素
  • 要使用for语句处理多维数组时,除了最内层的循环外,其他循环的控制变量都应该是引用类型。
for (auto & row : a)            // int (&row)[4],第一维的引用
    for (auto & col : row)      // int &col,数值的引用,以便修改原始值
        col *= 2;

for (auto & row : a)            // 同样需要引用,避免数组转换成指针
    for (auto col : row)        // 不用引用,因为不需要修改原始值
        cout << col << endl;        

for (auto row : a)              // int *row
    for (auto col : row)        // 错误:无法遍历指针
        cout << col << endl;

猜你喜欢

转载自blog.csdn.net/l773575310/article/details/79008646