摘自《C++ 17 入门经典》。几乎不会再更新。
文章目录
- 使用花括号初始化变量
- 零初始化
- 使大整型字面量更加易读
- 二进制的整型字面量
- `size_t` 类型
- 浮点数的特殊情况:NaN(Not a Number)和 infinity
- 显式类型转换
- 获得数值的上下界
- 不要混合使用 `cout` 和 `wcout`
- `auto` 与 `std::initializer_list`
- 运算结果至少是 `int`,不会是 `short`
- 强类型的枚举
- `switch` 定义变量的限制
- `if` 和 `switch` 语句的初始化
- 使用 `std::array` 代替普通数组
- 使用 `std::size` 获取数组的大小
- 使用 `auto*`
- 常量指针与指向常量的指针
- `new[]`
- 指向数组的指针
- 智能指针
- 包含 `memory` 头文件
- `unique_ptr`
- 使用 `std::make_unique`
- 创建指向数组的指针
- `get` 方法
- `reset` 方法
- `release` 方法
- `share_ptr`
- `std::string::data` 方法
- `std::string` 字面量
- `std::to_string` 函数
- `std::stoi` 函数
- 原始字符串
使用花括号初始化变量
代码:三种初始化变量的方式
int a = 1.1;
int b(1.2);
int c{ 1.3 };
使用花括号初始化变量的特点有两个:
- 允许以相同的方式初始化所有变量,这一点我们之后再进行进一步的讨论;
- 当发生收缩转换时,编译器将会报错而非警告。
零初始化
使用花括号进行初始化时,若想要让默认值为 0,可以省略 0。
代码:零初始化
int a = 0;
int b(0);
int func();
int c{};
注意在使用圆括号进行初始化时并不能省略这个 0,否则这表示的将会是一个函数。
使大整型字面量更加易读
代码:数字分隔符
auto a{ 1'0'0'0'0000'0000 };
二进制的整型字面量
代码:二进制整型字面量
auto a{ 0b1011 }, b{ 0B1011 };
size_t
类型
sizeof
运算符得到的结果是一个 size_t
类型的整数,size_t
的宽度取决于目标平台。size_t
是无符号的。
一般而言,size_t
可以直接被使用。它还在 cstddef
头文件中被定义。
浮点数的特殊情况:NaN(Not a Number)和 infinity
有关它们的运算法则,可以在需要时进行测试或查阅。
可以使用 cmath
中的 std::isinf()
函数和 std::isnan()
函数判断一个浮点数是否是 NaN 或者 infinity。
显式类型转换
代码:显式类型转换
int a{ static_cast<int>(1.1) };
获得数值的上下界
使用 limits
头文件中的 numeric_limits
类获取我们需要的值。
代码:numeric_limits
constexpr auto a = std::numeric_limits<int>::min();
constexpr auto b = std::numeric_limits<int>::max();
constexpr auto c = std::numeric_limits<double>::min();
constexpr auto d = std::numeric_limits<double>::max();
constexpr auto e = std::numeric_limits<double>::lowest();
不要混合使用 cout
和 wcout
是否使用宽字符输出,取决于第一个输出操作是使用的 cout
还是 wcout
。
auto
与 std::initializer_list
仅在 cpp 17 中满足下列规则:
auto a{ 1 };
auto b = { 1 };
auto c = { 1, 2 };
auto d{ 1, 2 };
运算结果至少是 int
,不会是 short
强类型的枚举
代码:新的枚举
int main()
{
enum OldOne
{
ichi,
ni,
sann
};
OldOne a = OldOne::ichi;
a = static_cast<OldOne>(2);
a = sann;
enum class NewOne
{
ICHI = 1,
NI,
SANN
};
NewOne b = NewOne::ICHI;
b = static_cast<NewOne>(2);
b = SANN;
return 0;
}
switch
定义变量的限制
在 switch
中,如果变量被定义的同时被初始化,就不能绕过变量的定义而进入变量的作用域。
代码:错误的 switch
switch (0)
{
case 1:
int a{ 1 };
default:
break;
}
以上代码中,在 default
后面是可以访问变量 a
,即在作用域范围内,但是在进入 default
时,变量 a
并没有被初始化,这是不允许的。
if
和 switch
语句的初始化
代码:如果我是 for
if (int i{ 1 }; i <= 10);
switch (int i{ 1 }; i);
使用 std::array
代替普通数组
需要包含 array
头文件。
使用 std::size
获取数组的大小
支持普通数组和 array
。
使用 auto*
如果要用指针初始化一个变量,建议使用 auto*
而非 auto
,因为在使用 auto*
时,若给定值不是一个指针,编译将不会通过。
常量指针与指向常量的指针
const
在类型前,指向常量的指针,即指针可以指向别处,但修改不了被指向的地方。
const
在星号后,常量指针,即指针本身不可指向别处,但可以修改被指向的地方。
new[]
在使用类似于 new int[3] { 0, 1, 2 }
的代码时,不能省略表示大小的 3
。
指向数组的指针
代码:奇怪的 new
int main()
{
auto a{ new int[3][4] {} };
int(*b)[4]{ new int[3][4] {} };
delete[] a;
delete[] b;
}
只有第一维能够是动态的,后面的维度必须是 constexpr
的。
智能指针
包含 memory
头文件
unique_ptr<T>
该对象储存唯一的地址,并且这个地址被该对象独占。释放该对象时,其对应的指针也会释放。
代码:unique_ptr
std::unique_ptr<int> p{ new int {233} };
使用 std::make_unique<T>
代码:make_unique
auto p{ std::make_unique<int>(666) };
创建指向数组的指针
代码:指向数组的智能指针
std::unique_ptr<int[]> p{ std::make_unique<int[]>(10) };
p[0] = 1;
get
方法
使用 get
方法能够获得智能指针包含的地址。使用 get
函数,务必保证不会长时间保存得到的指针。
reset
方法
reset
方法可以修改智能指针指向的值,并且在此之前对已有的指针进行删除操作。
代码:reset 方法
auto p{ std::make_unique<int>(233) };
p.reset(new int{ 666 });
release
方法
使用 release
方法可以将已经存在的指针宣布由自己管理,智能指针不再插手,将被设为指向 nullptr
。
代码:release 方法
auto p{ std::make_unique<int>(233) };
auto* t = p.release();
delete t;
share_ptr<T>
share_ptr
在内部对同一个地址有一个引用计数。与 unique_ptr
不同的是,可以用一个 share_ptr
对另一个 share_ptr
进行赋值。
share_ptr
没有 release
方法和 get
方法,其他内容大同小异。
std::string::data
方法
在 cpp 17,data
方法将返回一个非 const
的指针,而在之前的标准中得到的指针是 const
的。
std::string
字面量
首先使用 using namespace std::string_literals;
,然后在字符串字面量后面加上后缀 s
,就能得到一个 std::string
对象。
using namespace std::string_literals;
"literal"s;
std::to_string
函数
该函数能将基本类型转换为 std::string
。
std::stoi
函数
该系列函数将 std::string
转换为数字。
原始字符串
代码:原始字符串
LR"(Row)";
R"(row)";
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)