1. 结构化绑定
结构化绑定允许声明多个变量,这些变量使用数组、结构体、pair或元组中的元素以初始化。例如,假设有下面的数组:
std::array values { 11, 22, 33 };
可声明3个变量x、y和z,像下面这样使用数组中的3个值进行初始化。注意:必须为结构化绑定使用auto关键字。例如,不能用int替代auto。
auto [x, y, z] { values };
使用结构化绑定声明的变量数量必须与右边表达式中的值数量匹配。
如果所有非静态成员都是公有的,也可将结构化绑定用于结构体。例如:
struct Point {
double m_x, m_y, m_z;
};
Point point;
point.m_x = 1.0;
point.m_y = 2.0;
point.m_z = 3.0;
auto [x, y, z] { point };
正如最后一个例子,以下代码将pair中的元素分解为单个变量:
std::pair myPair { "hello", 5 };
auto [theString, theInt] { myPair }; // decompose using structured bindings.
std::cout << std::format("theString: {}\ttheInt: {}\n", theString, theInt);
2. 循环
2.1 while循环
只要条件表达式的求值结果为true,while循环就会重复执行一个代码块。例如,下面的代码会输出“This is silly."五次。
int i { 0 };
while ( i < 5 ) {
std::cout << "This is silly.\n";
++i;
}
在循环中使用break关键字立刻跳出循环并继续执行从程序。关键字continue可用来返回到循环顶部并对while表达式重新求值。然而,在循环中使用continue经常被认为是不良的编码风格,因为它们会使程序的执行产生无规则的跳转,应该慎用。
2.2 do/while循环
C++还有一个版本的while循环,称为do/while循环。其运行方式类似于while循环,但会首先执行代码,而判断是否继续执行的条件检测被放在结尾处。如果想让代码块至少执行一次,并且根据某一条件确定是否多次执行,就可以使用这个循环版本。下面的代码尽管条件为false,但仍会输出"This is silly."一次。
int i { 100 };
do {
std::cout << "This is silly.\n";
++i;
} while ( i < 5 );
2.3 for循环
for循环提供了另一种循环语法。任何for循环都可转换为while循环,反之亦然。然而,for循环的语法一般更简便,因为可看到循环的初始表达式、结束条件以及每次迭代结束后执行的语句。在下面的代码中,i被初始化为0;只要i小于5,循环就会继续执行;每次迭代结束时,i的值会增1。
for ( int i { 0 }; i < 5; ++i) {
std::cout << "This is silly.\n";
}
2.4 基于范围的for循环
基于范围的for循环是第四种循环,这种循环允许方便地迭代容器中的元素。这种循环类型可用于C风格数组、初始化列表,可用于任何具有返回迭代器的begin()和end()方法的类型,例如std::array、std::vector以及其他所有标准库容器。
下面首先定义了一个包含4个整数的数组,此后基于范围的for循环遍历数组中的每个元素的副本,输出每个值。为在迭代元素时不制作副本,应使用引用变量。
std::array arr { 1, 2, 3, 4 };
for ( int i : arr ) {
std::cout << i << "\n";
}
从C++20开始,可以在基于范围的for循环中使用初始化器:
for ( <initializer>; <for-range-declaration> : <for-range-initializer>) {
<body>
}
任何在<initializer>中引入的变量只能被用于<for-range-initializer>和<body>中,不能被用于基于范围的for循环之外。示例如下:
for (std::array arr { 1, 2, 3, 4}; int i : arr ) {
std::cout << i << "\n";
}
3. 初始化列表(C++11)
初始化列表在<initializer_list>头文件中定义;利用初始化列表,可轻松地编写能接收可变数量参数的函数。std::initializer_list是一个模板,要求在尖括号之间指定列表中的元素类型,这类似于指定vector中存储的对象类型。示例如下:
int makeSum(std::initializer_list<int> values) {
int total { 0 };
for ( int value : values ) {
total += value;
}
return total;
}
makeSum()函数总是接收一个整数类型的初始化列表作为参数。可按如下方式使用该函数:
int a { makeSum({ 1, 2, 3 }) };
int b { makeSum({ 10, 20, 30, 40, 50, 60 }) };
初始化列表是类型安全的,列表中的所有元素必须为同一类型。对于此处的makeSum()函数,初始化列表中的所有元素都必须是整数。尝试使用double数值进行调用,将导致编译器生成错误或警告。
4. C++中的字符串
在C++中使用字符串有两种方法。
C风格的字符串:用字符数组表示字符串。
C++风格的字符串:将C风格的表示封装到一种易于使用和更安全的string类型中。
C++中std::string类型在<string>头文件中定义,C++ string的用法与基本类型几乎相同。示例如下:
std::string myString { "Hello, World" };
std::cout << std::format("The value of myString is {}\n", myString);
std::cout << std::format("The second letter is {}\n", myString[1]);
参考
[比] 马克·格雷戈勒著 程序喵大人 惠惠 墨梵 译 C++20高级编程(第五版)