C++11 新特性快速一览

从 C++98 到 C++11,C++11 标准经历了十几年的沉淀。尽管后来更新速度越来越快,又出现了 C++14、C++17 等等,但 C++11 是必学的经典标准。

主要特性目录:

C++11 新特性快速一览

关键字及新语法

auto关键字及用法

auto 并没有让 C++ 成为弱类型语言,只是使用 auto 的时候,编译器根据上下文,确定 auto 变量的真正类型。

auto AddTest(int a, int b) { // auto 可以作为函数的返回值类型

return a + b;

}

int main() {

auto index = 10; // 自动识别类型为 int

auto res = AddTest(1,2);

std::cout << "index:" << index << std::endl; // index:10

std::cout << "res:" << ret << std::endl; // res: 3

}

但是注意 auto 作为函数返回值时,必须用于定义函数,不能仅仅声明函数。

nullptr 关键字及用法

在 nullptr 出现之前存在什么问题呢?首先,NULL 不是一个关键字,而只是一个宏(macro):

#define NULL 0

考虑这样一个函数重载的情形:

void foo(int) {} // #1

void foo(char*) {} // #2

int main() {

foo(NULL); // 调用 #1 还是 #2 ?

}

为了解决这种二义性,C++11 引入了关键字 nullptr,它作为一种空指针常量。foo(nullptr); 会毫无异议地调用函数 #2。

for 循环语法

原先 C++ 的 for 循环是没有像 foreach 那样的用法的。现在 C++ 11 的 for 循环语法再结合 auto 关键字可以大大简化开发代码:

int main() {

int numbers[] = {1, 2, 3, 4, 5};

for (auto number : numbers)

std::cout << number << std::endl;

}

STL容器

std::array

相对于数组而言,std::array 增加了 STL 的各种迭代器、算法、操作方法等,更加安全、方便。

相对于 std::vector 而言,std::array 提供了静态数组,编译时确定大小、更轻量、更效率,当然也比 std::vector 有更多局限性。std::array 差不多就是 std::vector 和 普通数组的中和版本。

#include

int main() {

std::array arrayDemo = {1, 2, 3, 4};

for (auto it : arrayDemo)

std::cout << it << std::endl;

int arrayDemoSize = sizeof(arrayDemo);

std::cout << "arrayDemo size:" << arrayDemoSize << std::endl; // 16

return 0;

}

std::forward_list

std::forward_list 为新增的线性表,与 list 区别在于它是单向链表。forward_list 可以看作是对 C 语言风格的单链表的封装,仅提供有限的接口,和 C 中它的实现相比,基本上不会有任何开销。当不需要双向迭代的时候,与 std::list 相比,该容器具有更高的空间利用率。

#include

int main() {

std::forward_list numbers = {1, 2, 3, 4, 5, 4, 4};

for (auto number : numbers)

std::cout << number << " "; // 1 2 3 4 5 4 4

numbers.remove(4); // 移除值为 4 的节点

std::cout << "numbers after remove:" << std::endl;

for (auto number : numbers)

std::cout << number << " "; // 1 2 3 5

return 0;

}

std::unordered_map

C++ unordered_map:https://www.jianshu.com/p/56bb01df8ac7

std::unordered_set

std::unordered_set 的数据存储结构也是 hashtable+list 的方式,此外,std::unordered_set 在插入时不会像 std::set 一样自动排序。

#include

#include

int main() {

std::unordered_set unorder_set;

unorder_set.insert(7);

unorder_set.insert(5);

unorder_set.insert(3);

unorder_set.insert(4);

unorder_set.insert(6);

for (auto itor : unorder_set)

std::cout << itor << " "; // 7 5 3 4 6

std::set set;

set.insert(7);

set.insert(5);

set.insert(3);

set.insert(4);

set.insert(6);

for (auto itor : set)

std::cout << itor << " "; // 3 4 5 6 7

}

多线程

在 C++11 以前,C++ 的多线程编程均需依赖系统或第三方接口实现,一定程度上影响了代码的移植性。C++11 中,引入了 boost 库中多线程的部分内容,形成标准后的接口与 boost 库基本没有变化,这样方便了使用者切换使用 C++ 标准接口。

std::thread

C++11 的 std::thread 解决了 boost::thread 中参数限制的问题,这大概都是得益于 C++11 的可变参数的设计风格。thread 类内的三个方法:

std::atomic

当我们在编程中想对共享资源进行保护时,很自然地就会想到加锁,但是锁机制会大大增加时间开销。std::atomic 为 C++11 封装的原子数据类型。从功能上看,原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的操作。从实现上,大家可以理解为这些原子类型内部自己加了锁。

下面例子中,我们使用 100 个线程, 模拟一万次网页点击:

#include

#include

#include

#include

// 用原子数据类型作为共享资源的数据类型

std::atomic_int total(0);

//long total = 0;

void click(){

for(int i=0; i<100;++i)

// 仅仅是数据类型的不同而已,对其的访问形式与普通数据类型的资源并无区别

total += 1;

}

int main()

{

// 创建100个线程模拟点击统计

std::list threads;

for(int i=0; i<100;++i)

threads.push_back(std::thread(click));

for (auto& th : threads)

th.join();

std::cout<<"result:"<

return 0;

}

std::condition_variable

线程休眠在多线程编程中使用非常频繁,经常需要等待一些异步执行的条件的返回结果。当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex)来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

#include // std::cout

#include // std::thread

#include // std::mutex, std::unique_lock

#include // std::condition_variable

std::mutex mtx; // 全局互斥锁

std::condition_variable cv; // 全局条件变量

bool ready = false; // 全局标志位

void do_print_id(int id) {

std::unique_lock lck(mtx); // 进入休眠

while (!ready) // 如果标志位不为 true, 则等待

cv.wait(lck); // 进入休眠, 当前线程被阻塞, 当全局标志位变为 true 之后,

// go() 函数内调用 notify_all() 函数后, 线程被唤醒, 继续往下执行打印线程编号 id

std::cout << "thread " << id << ' ';

}

void go() {

std::unique_lock lck(mtx);

ready = true; // 设置全局标志位为 true

cv.notify_all(); // 唤醒所有线程

}

int main() {

std::thread threads[10];

for (int i = 0; i < 10; ++i)

threads[i] = std::thread(do_print_id, i);

std::cout << "10 threads ready to race... ";

go();

for (auto & th:threads)

th.join();

}


输出结果(顺序是不一定的):

10 threads ready to race...

thread 9

thread 2

thread 3

thread 8

thread 7

thread 6

thread 5

thread 4

thread 1

thread 0

智能指针内存管理

智能指针及其作用:https://www.jianshu.com/p/22856998b4c3

简单画一下指针、智能指针对象和计数器之间的关系。

文章部分素材源自:CPP程序员

展开阅读全文

页面更新:2024-05-28

标签:数组   线程   指针   全局   原子   语法   数据类型   函数   接口   标志   关键字   对象   类型   快速   智能

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top