C++学习(c++17)——1.1 C++基础知识
假期花了2个月,连滚带爬地白嫖完C++的一个教学视频(总时长144h),然后开始尝试去运用知识做一些小项目。但实验室的大佬吴学长的魔鬼提问把我又打回原形,然后这次准备拿着资料去踏踏实实学习(把Cpppp放在学校宿舍真是一个错误的决定。) 这次的学习主要围绕的是c++17的一些特性,并且巩(完)固(善)假期里面看视频学习的c++。【学校有小程序大赛,又有老师组织的论文学习的作业,啊啊啊,我想学会分身术】
注意注意:此系列笔记内容适用对象为和我一样白嫖了网课,基础却不扎实或者想要学习c++17标准的人。
命名空间
C++17允许方便地使用嵌套的命名空间。
c++17前:
namespace MyLibraries{
namespace NetWorking{
namespace FTP{
/*...*/
}
}
}
C++17:
namespace MyLibraries::NetWorking::FTP{
/*...*/
}
//同时可使用名称空间别名:
namespace MyFTP = MyLibraries::NetWorking::FTP;
字面量
数值字面量中可以使用数字分隔符(一个单引号),例如
- 23'456'789
- 0.123'456f
C++17中增加了对十六进制浮点字面量的支持,如0x3.ABCp-10、0Xb.cp123(p-10指*2的-10次方)
数据类型
C++17中增加了std::byte来表示单个字节(在c++17之前,用字符或无符号字符来表示一个字节,但那些类型感觉像在处理字符。std::byte则指明意图——内存中的单个字节)
std::byte b{42};
注意:
- 需要
头文件。 - std::byte的初始化需要使用单元素列表进行直接列表初始化。
枚举类型
建议用类型安全的enum class强类型枚举来替代类型不安全的enum枚举。
条件语句
if语句
C++17中允许在if语句中包括一个初始化器,语法如下:if (
switch语句
当一个case表达式后的语句执行完后,如果没有遇到"break",则会继续执行下一个case后的语句,这被称为"fallthrough"。(因为它经常成为bug来源,所以编译器会生成警告信息)
C++17中,可用使用[[fallthrough]]特性,来告诉编译器这是特意为之。
C++17中,switch和if一样支持使用初始化器:switch(
函数
函数返回类型的推断(auto)
C++14允许要求编译器自动推断出函数的返回类型。要使用这个功能,需要把auto指定为返回类型:
auto addNumber(int number1,int number2){
return number1 + number2;
}
编译器根据 return后的表达式 推断返回类型。函数中可以有多个return,但是应该解析为同种返回类型。也可以包含递归调用,但是第一个return语句必须是非递归调用(有递归出口)。
当前函数的名称(func)
每个函数都有一个预定义的局部变量______func______,其中包含当前函数的名称。这个变量的一个用途是用于日志记录。
数组
C风格的数组【建议改用array和vector】
要获取基于栈的c风格数组的大小(元素个数),可以使用C++17 std::size()函数(需要
int myArray[3];
unsigned int arraySize = std::size(myArray);
C++17之前获取元素个数:
unsigned int arraySize = sizeof(myArray) / sizeof(myArray[0])//sizeof操作符返回实参的大小(单位为字节)
std::array
std::array是一种大小固定的特殊容器。基本上是对c风格数组进行简单包装。
好处:
- 总是知道自身大小。
- 不会自动转换为指针,从而避免了某些bug。
- 具有迭代器,可以方便地遍历元素。
array<int, 3> arr = {1,2,3}
cout << "Array size:" << arr.size()<<";";
cout << "2nd element:" << arr[1];
上述代码的输出结果为Array size:3;2nd element:2。
std::vector
标准库提供的多个不同的非固定大小容器之一。vector是动态的,可以在运行时添加或者删除元素。
//Create a vector of integers
vector<int> myVector = { 11, 22};
//Add some more integers to the vector using push_back()
myVector.push_back(33);
myVector.push_back(44);
//Access elements
cout << "1st element: "<< myVector[0] << endl;
结构化绑定(structured bindings)
结构化绑定允许使用数组、结构、pair或元组中的元素来初始化多个变量。
例如,假设有下面的数组:
std::array<int, 3> values = {11, 22, 33};
那么可以同时声明三个变量,用这个数组来进行初始化【注意,结构化绑定必须要使用auto关键字】
auto [x, y, z] = values;
绑定的变量个数必须和右侧表达式中值个数一样。
且当所以非静态成员都是公有的情况下,才能将结构化绑定用于结构(struct)。
基于区间的for循环(Range-Based for Loop)
这是除了原本的while、do-while(至少执行一次的循环)、for循环外的第四种。这种循环允许方便地迭代容器中的元素。可用于C风格的数组、初始化列表,也可以用于具有返回迭代器的begin()和end()函数的类型,如std::array,std::vector等标准库容器。
std::array<int, 4> arr = {1, 2, 3, 4};
for(int i : arr){
std::cout << i << std::endl;
}
(若想迭代元素时不制作副本,则应使用引用变量)
初始化列表
在头文件<initializer_list>头文件中定义。利用初始化列表,可以用于可变数量参数的函数。
#include <initializer_list>
using namespace std;
int makeSum(initializer_list<int> 1st){
int total = 0;
for(int value : 1st){
total += value;
}
return total;
}
初始化列表是类型安全的。