首页 > 编程语言 >罗剑锋的C++实战笔记-学习笔记(2)

罗剑锋的C++实战笔记-学习笔记(2)

时间:2022-11-28 12:00:56浏览次数:46  
标签:std 容器 函数 auto 代码 C++ 算法 笔记 剑锋

书接上文,三句名言镇楼。

三句名言镇楼

  • 任何人都能写出机器能看懂的代码,只有优秀的程序员才能写出人看懂的代码

  • 两种写程序的方式:把代码写的非常复杂,以至于"看不出明显错误"。把代码写的非常简单,以至于"明显看不出错误"。

  • 把正确的代码改快速,要比把快速的代码改正确,容易得太多。

处理错误方案

  • 错误码:检查函数执行返回值或者 errno 码,依此为下一步行动依据。
    缺点:

    1. 将业务代码和错误处理代码混在一起。
    2. 错误码可以被忽略,可能会引发更多错误
  • 异常

    1. 通过 throw 抛出异常,在 catch 中统一处理异常,分离业务代码和错误处理代码。
    2. 不能被忽略
    3. 适用于无法使用错误码的场合

有一种包裹整个函数体的异常写法:


void some_fun()
try
{

}
catch(...)
{

}

上述写法可以捕获some_fun执行过程中所有可能的异常,而且少一级缩进,处理逻辑更清晰。

一般认为,普通构造、拷贝构造、转移构造、析构函数应尽量声明为noexcept,告知编译器据此进行优化。析构函数保证绝对不会抛异常。

Lambda

Lambda函数内部的捕获变量,需要在函数体声明前方声明,才能正确捕获。

	auto f2 = [&]()
	{
		x_ += 10; // 在函数体之前,是看不到x_变量的,编译出错。
	};
	int x_ = 33;   
	

一句话,按需捕获,最小化对外部的影响。每个 lambda 表达式的类型都是唯一的,可使用 std::function 类来存储。

字符串和容器的区别

字符串是文本,内部的字符之间是强关系,顺序不能随便调换,否则就失去了本意,通常视为一个整体来处理。

容器是容纳某种类型数据的集合,内部元素之间没有任何关系,对容器来说,可以随意增删改,以单个元素为操作单位。

使用R来表示原始字符串,比如


auto str1 = R"(\r\n\t)";    // 表示 str1 为 \r\n\t 这6个字符。

STL中的算法

相比于手写for循环,STL中的内置算法是更高层次的抽象和封装。 关注做了什么,而不关心是怎么做的。

比如说,统计一个序列中大于2的元素个数。


#include <algorithm>
auto n = std::count_if(begin(v), end(v), [](auto& v){
    return v > 2;
});

算法通过迭代器间接访问容器内部元素,分离了数据和对数据的操作,使得算法适用范围更广,更灵活。为了兼顾效率,在通用算法之上,STL针对mergesortunique等算法,提供了各容器的特化版本,针对数据结构特点进行针对性的优化。例如list容器有sort成员函数。

打印数组中的元素,可使用如下套路:


auto print = [](const auto& x) {
	cout << x << ",";
};

std::sort(begin(arr), end(arr));        // 先排序
for_each(cbegin(arr), cend(arr), print);   //  再输出

for_each将元素遍历和对每个元素的操作分开,含义明确,达到更好的封装。

排序算法

  • 要求稳定,使用 stable_sort
  • 选出前几名(TopN),并要求有序,使用 partial_sort
  • 选出前几名(BestN),不要求有序,使用 nth_element。 该算法适用于中位数、百分位数
  • 分成两组,使用 partition
  • 求最大、最小值,使用 minmax_element

多线程开发实践

  • 仅调用一次:std::call_once函数,在多线程调用时,保证可调用对象只会调用一次。
  • 线程局部存储: thread_local关键字。
  • 原子变量:原子变量禁用拷贝构造函数,不能使用=赋值,只能用圆括号或花括号。
  • 将线程往上抽象一层,运行一个异步任务,可使用 std::async
#include <future>
#include <thread>
using std::this_thread::sleep_for;
#include <chrono>
void test_async()
{
	auto task = [](auto x) {
		cout << "begin sleep for" << x << endl;
		sleep_for(std::chrono::milliseconds(x * 1000));
		cout << "end sleep for" << x << endl;
		return x;
	};

	auto f = std::async(task, 50); // 启动一个异步任务
	f.wait();      // 等待任务完成
	assert(f.valid());     // 确实已经完成任务
	cout << f.get() << endl;     // 获得任务执行结果(只能调用一次)
}


应用层常用库

数据交换格式

  • json: 纯文本,容易阅读,编辑,适用性最广。可使用nlohmann/json.hpp来解析
  • MessagePack : 二进制格式,小巧高效,但只对基本类型和标准容器进行序列化/反序列化。
  • ProtoBuffer: Google出品的工业级数据格式,注重安全和性能。

网络通讯

  • libcurl: 著名开源curl项目的底层核心库,C语言编写,兼容性强。cprlibcurlc++11封装版本,常用于客户端程序。
  • ZMQ: 网络通讯库,支持多种通讯模式,可把消息队列直接嵌入应用程序。

标签:std,容器,函数,auto,代码,C++,算法,笔记,剑锋
From: https://www.cnblogs.com/cherishui/p/16931815.html

相关文章

  • redisOject 和 底层数据结构对应 学习笔记
    笔记摘抄自https://pdai.tech/md/db/nosql-redis/db-redis-data-type-enc.htmlredisObject查看编码命令setk11objectencodingk1setk2helloobjectencoding......
  • 罗剑锋的C++实战笔记(学习笔记1)
    本系列文章记载学习一门在线课程罗剑锋的C++实战笔记过程中的心得体会,只会记录新增加的知识点,那些心中已熟透的知识点,不会重复记录。c++的主战场在Linux上,现在开发Wi......
  • 驱动开发学习笔记---阻塞和非阻塞IO
    一、阻塞和非阻塞简介当应用程序对设备驱动进行操作的时候,如果不能获取到设备资源,那么阻塞式IO就会将应用程序对应的线程挂起,直到设备资源可以获取为止。对于非阻塞IO......
  • C++中的Pointer member dereference(D-reference) operator
    在C++中,比如我们可以把一个结构体struct的地址赋给一个指针pointer然后使用这个指针去访问这个结构体中的元素时,可以使用pointermemberD-referenceoperator: ->用来......
  • C++ ---获取类成员函数地址
    #include<iostream>classTA{public:inta;voidTA1(){//this->a=5;printf("a=%d\n",a);}voidTA2(){......
  • Django-课程介绍-笔记
    软件框架问题1:什么是软件框架?举个简单的例子,对于一个公司来说,公司中有各个职能部门,每个部门各司其职,通过部门之间的配合来完成工作,这些部门就形成了一个公司的组织架构。从......
  • Django-1.入门-笔记
    本节课是通过Django框架最终完成一个"图书-英雄"信息管理的小例子。目标对使用django框架有一个全面的认识,包括开发流程、基本概念要素,并不针对某个概念知识点详细拆解,后续......
  • Django-1.1搭建环境-笔记
    虚拟环境在开发过程中,当需要使用python的包时可以联网安装sudopip3install包名称使用如上命令,会将包安装到/usr/local/lib/python3.5/dist-packages下。产生的问题如果在......
  • Django-1.2创建项目-笔记
    创建图书管理项目我们以一个电商网站为例,网站上有跟用户有关的页面,有跟商品有关的页面,还有跟订单有关的页面,这样的一块内容其实就是网站的一个功能模块。在django中,项目的组......
  • 区块链学习笔记
    这是我学习北京大学肖臻老师《区块链技术与应用》公开课的学习笔记课程地址:北京大学肖臻老师《区块链技术与应用》公开课比特币比特币中的密码学原理比特币被称为加......