C++ 学习笔记——十二、探讨 C++ 新标准
创始人
2025-05-30 05:10:52
0

目录:点我

一、复习

1. 新类型

C++ 11 新增了类型 long long 和 unsigned long long ,以支持 64 位(或更宽)的整型;新增了类型 char16_t 和 char32_t ,以支持 16 位和 32 位的字符表示;还新增了“原始字符串”。

2. 统一的初始化

C++ 11 扩大了用大括号括起的列表(初始化列表)的适用范围,使其可用于所有内置类型和用户定义的类型(即类对象)。使用初始化列表时,可添加等号,也可不添加:

// 常规类型
int x = {5};
double y {2.75};
short quar[5] {4, 5, 2, 76, 1};
int * ar = new int [4] {2, 4, 6, 7};  // new表达式// 类
class Stump {
private:int roots;double weight;
public:Stump(int r, double w) : roots(r), weight(w) {}
};
Stump s1(3, 15.6);  // old style
Stump s2{5, 43.4};  // c++11
Stump s3 = {4, 32.1};  //c++11// 缩窄转换
char c1 = 1.57e27;  // double to char, allow but undefined behavior
char c2 = 459585821  // int to char, allow but undefined behavior
// 防止缩窄转换
char c1 {1.57e27};  // double to char, not allow
char c2 = {459568434};  // int to char, out of range, not allow
// 允许转换为更宽的类型
char c1 {66};  // int to char, in range, allow
double c2 = {66};  // int to double, allow// 模板
vector a1(10);  // 未初始化的,大小为10的向量
vector a2{10};  // 初始化列表,大小为1,值为10;
vector a3{4, 6, 1};  // 初始化列表,大小为3,值为4 6 1

3. 声明

C++ 11 提供了多种简化声明的功能:

auto maton = 112;  // 自动推断 int
auto pt = &maton;  // int *
double fm(double, int);
auto pf = fm;  // double (*)(double, int)
decltype(x) y;  // 将y类型转换为x的类型
double x; int n;
decltype(x*n) q;  // double
decltype(&x) pd;  // double *// 模板常用方法
template
void ef(T t, U u) {decltype(T*U) tu;  // 模板实例化时确定类型...
}// 返回类型后置
double f1(double, int);  // 传统语法
auto f2(double, int) -> double;  // 新语法,返回double
auto eff(T t, U u) -> decltype(T*U);  // 常规用法// 模板别名
typedef std::vector::iterator itType;  // 传统别名,不能用于模板部分具体化
using itType = std::vector::iterator;  // C++ 11新方法,可以用于模板部分具体化
template
using arr12 = std::array;  // 模板部分具体化// 空指针
nullptr <=> 0

4. 智能指针

如果在程序中使用 new 从堆分配内存,等到不再需要时,应使用 delete 释放,新增智能指针帮助自动化完成该过程。C++ 11 摒弃了 auto_ptr ,新增了 unique_ptr 、shared_ptr 、weak_ptr 。

5. 异常规范

用于指出函数可能引发哪些异常:

// 传统方法,因不好用被C++11摒弃
void f501(int) throw(bad_dog);  // 抛出bad_dog异常
void f733(long long) throw();  //  不会引发异常
// 第二种情况可能有意义,因此新增关键字noexcept
void f875(short, short) noexcept;  // 不会引发异常

6. 作用域内枚举

传统枚举:

  • 提供了一种创建名称常量的方法,但其类型检查相当低级。
  • 枚举名的作用域为枚举定义所属的作用域,这意味着如果在同一个作用域内定义两个枚举,它们的枚举成员不能同名。
  • 枚举可能不是可完全移植的,因为不同的实现可能选择不同的底层类型。

为解决这些问题,新增枚举:

// 旧枚举
enum old {yes, no, matbe};
// 新枚举,需要显示指定枚举成员作用域
enum class new1 {never, sometimes, often, always};
enum struct new2 {never, lever, sever};

7. 对类的修改

禁止隐式转换运算符:

class Plebe {operator int() const;explicit operator double() const;
};
Plebe a, b;
int n = a;  // 隐式转换为int
double x = b;  // 隐式转换为double,not allow
x = double(b);  // 显示转换为double,allow

类内成员初始化:

class Session {int mem1 = 10;  // 类内初始化double mem2 {1966,.54};  // 类内初始化short mem3;
public:Session(){}Session(short s) : mem3(s) {}Session(int n, double d, short s) : mem1(n), mem2(d), mem3(s) {}
};

可以使用等号和大括号初始化,但不能使用圆括号。通过类内初始化可以避免在构造函数内编写重复代码。

8. 模板和 STL

基于范围的 for 循环:

vector v(10);
for(int i : v)cout << i << endl;

新增 STL 容器:

容器作用
forward_list单向链表
unordered_map无序 map
unordered_multimap无序、可重复 map
unordered_set无序 set
unordered_multiset无需、可重复 set
array数组

新增 STL 方法:

方法说明
cbegin()指向容器第一个元素,并将元素视为 const
cend()指向容器最后一个元素的后面,并将元素视为 const

对 valarray 进行升级,添加了 begin() 和 end() ,使之可以被迭代器访问,从而能够将基于范围的 STL 算法用于该容器。

摒弃 export ,原本作用为让程序员能够将模板定义放在接口文件和实现文件中,其中前者包含原型和模板声明,后者包含模板函数和方法的定义。

新增尖括号的识别,避免了与 >> 运算符混淆。

9. 右值引用

左值是一个表示数据的表达式(变量名、解除引用的指针),最初只能出现在赋值语句左边,但是随着 const 引入,也可以出现在赋值语句右边:

int n;
int * pt = new int;
const int b = 101;  // 不能修改b
int & rn = n;  // 引用n,即取到了n的地址
int & rt = *pt;  // 取到了指针的地址
const int & rb = b;  // 取到了b的地址,但不能修改rb

右值则是一个表示运算的表达式(不能对其赋值),不能应用取地址符,这种方式更像是创建并保存了一个表达式结果的副本,并引用了这个副本:

int x = 10;
int y = 23;
int && r1 = 13;
int && r2 = x + y;  // r2关联运算的结果,因此改变x或y不影响r2
double && r3 = sqrt(2.0);
double *p = &r3;  // 可以取到右值的地址

二、移动语义和右值引用

1. 移动语义

vector vstr(20000, string(1000));  // 2w个string,每个string有1k个char
vector vstr_copy1(vstr);

vectorstring 类都使用动态内存分配,因此它们必须定义使用某种 new 版本的拷贝构造函数。为初始化对象 vstr_copy1 ,拷贝构造函数 vector 将使用 new 给 2 万个 string 对象分配内存,而每个 string 对象又将调用 string 的拷贝构造函数,该构造函数使用 new 为 1 千个字符分配内存。接下来全部的字符都将从 vstr 控制的内存种复制到 vstr_copy1 控制的内存中。这样的工作量巨大,并且存在问题:

vector allcaps(const vector & vs) {vector tmp;// todo: tmp存储了vs全大写版本的数据return tmp;
}
vector vstr(20000, string(1000));
vector vstr_copy1(vstr);  // 拷贝vstr
vector vstr_copy2(allcaps(vstr));  // 创建tmp变量,函数运行结束时删除tmp变量,然后返回其它的副本,非常浪费资源

解决这个问题的方法为不删除 tmp 变量,而是转移所有权,该操作称为移动语义(move semantics),这样避免了删除和拷贝原数据。要实现它,需要让编译器直到何时需要复制,何时不需要,这就是右值发挥作用的地方。可以定义两个构造函数,一个是常规拷贝构造函数,使用 const 左值引用作为参数,这个引用关联到左值实参,如语句 1 的 vstr ;另一个是移动构造函数,使用右值引用作为参数,该引用关联到右值实参,如语句 2 种 allcaps 函数的返回值 tmp 。拷贝构造函数可执行深复制,而移动构造函数只负责调整记录(转换所有权)。由于移动构造函数可能修改其实参,因此右值引用不应是 const 。

Useless::Useless(Useless && f) : n(f.n) {  // 此处的f可以是运算表达式++ct;pc = f.pc;  // pc是一个指针(私有成员),指向现有数据f.pc = nullptr;  // 转换了所有权f.n = 0;  // 转换了所有权后原来的对象的长度变为0
}
Useless four(one + three);  // 传递一个对象运算表达式,这将生成临时对象,然后调用有移动构造函数

虽然右值引用可支持移动语义,但是需要执行两个步骤来执行。

  • 首先,让编译器直到何时可使用移动语义:
    Useless two = one;  // 拷贝构造函数
    Useless our(one + three);  // 移动构造函数
    
    对象 one 是左值,因此与左值引用匹配,调用拷贝构造函数;one + three 是右值,与右值引用匹配,调用移动构造函数。
  • 然后,编写移动构造函数,提供所需的方法。

2. 赋值

相关内容

热门资讯

和妈妈打羽毛球 和妈妈打羽毛球... 今天妈妈带我去打羽毛球,我老是没接到,但是,还有妈妈没接到的。。。。我玩的很开心!!!
白兔娃娃 白兔娃娃 白兔娃娃怎... 今天下午放学的时候包雨珊给我一个白兔娃娃。它的手脚又细又长,像个跳舞专家,我喜欢它。
准备住到爷爷家5天 准备住到爷... 今天妈妈说:“你可以住到爷爷家去,住到五天。”我听了欣喜若狂,吃过饭爸爸妈妈出去买东西,我在家收拾东...
今天玩得特开心 今天玩得特开心... 今天中午我和廖娟园下楼玩,我们参观了全校的三楼,因为它们是相连的。我们又去探险,参观校园,找到了蓄水...
最新或2023(历届)北京海淀... 海淀区  将增加中小学、幼儿园学位共计6000余个今年,海淀区将试点学区制改革,在现有12个小学学区...
最新或2023(历届)北京东城... 东城区新增9对深度联盟校1 月13日,在东城区人代会上,区长张家明作政府工作报告时提出,今年将新建9...
妈妈带我参加活动 妈妈带我参加... 今天下午妈妈带我去参加活动。活动内容介绍元宵节、做花灯、猜灯谜。做花灯的时候我都搞迷糊了,这里是卡哪...
day9-Python-元组和... Python-元组和集合 一.元组 1.什么是元组(tuple) """1)元组是容器型数据类型&#...
最新或2023(历届)北京西城... 西城区12所小学今年起直升优质初中今 年,裕中小学、西单小学、福州馆小学等12所小学中,30%符合条...
试题28 基础练习 回形取数 问题描述   回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,...
最新或2023(历届)北京昌平... 昌平区新增、改扩建中小学今年昌平区将新增、改扩建一批幼儿园、中小学,并增加幼儿园和小学入学学位,名校...
递归算法 - 分治算法 分治算法简介 分治算法(divide and conquer)是一种递归...
最新或2023(历届)北京丰台... 丰台区今年引进十余所优质校分校今年,丰台区将新增小学优质资源学位1100个,中学新增510个。记者从...
最新或2023(历届)北京通州... 通州区  3名校年内开建通州校区通州区三名小年内开间通州校区,它们分别为北京五中、景山学校、首师大附...
广州市教育局小升初民校必须面谈...  备受关注的最新或2023(历届)广州小升初新政细则至今不出台,民办学校“禁笔试改面谈”后如何面谈,...
SAP 发出商品业务配置 SAP发出商品业务配置,即: 出具销售发票时结转成本  一、业务背景&#...
最新或2023(历届)成都小升... 小升初政策 3月公布最新或2023(历届)小升初政策拟于3月公布,学生可通过就读小学、户籍所在地的区...
最新或2023(历届)广州小升... 最新或2023(历届)开始民校招生全面推行面谈关键词面谈 小学成绩 面谈名额相关政策:根据最新或20...
最新或2023(历届)成都小升... 最新或2023(历届)小升初政策拟于3月公布,学生可通过就读小学、户籍所在地的区(市)县教育行政部门...
最新或2023(历届)广州小升...  最新或2023(历届)广州小升初政策面临5大变革  最新或2023(历届),广州小升初的新政层出不...