嵌入式中《C++之旅》阅读笔记

constexpr

constexpr的隐含意思是在编译阶段求值,对于一些求值操作,如果声明为constexpr,那么会编译器会尝试在编译阶段进行计算求值,如果求值成功,则用结果进行替换。

一个常用的例子是如下:

constexpr int factorial(int n) {return n <= 1 ? 1 : (n * factorial(n - 1));
}int main() {auto num = factorial(10); // 编译阶段求得值,可从汇编查看return 0;
}

如果一个变量声明为constexpr,那么意味着在编译阶段就要获得其值,比如如下这个例子:

#include <iostream>constexpr int factorial(int n) {return n <= 1 ? 1 : (n * factorial(n - 1));
}int main() {int i = 10;constexpr auto num = factorial(i);return 0;
}

因为num被声明为constexpr,所以正如前面所说,在编译阶段求值,又因为i是一个非常量表达式,所以编译器报错如下:

<source>: In function 'int main()':
<source>:10:35: error: the value of 'i' is not usable in a constant expression10 |    constexpr auto num = factorial(i);|                                   ^
<source>:9:8: note: 'int i' is not const9 |    int i = 10;|        ^
Compiler returned: 1

if语句初始化

这个是自C++17才支持的,可以在if语句中进行初始化,随后进行条件判断,如下:

if (int a = 0; a != 10);

也可以像下面这样:

std::vector<int> v;
// operation
if (auto size = v.size()); 

引用赋值不会改变其初始指向

示例:

int x = 2, y = 3;
int &r1 = x;
int &r2 = y;
r1 = r2;
std::cout << x  << " " << y << " " <<  r1 << " " << r2;

在上述代码中,虽然最后r1被赋值为r2,但是其仍然指向x,这样的结果就是x的值也被修改了。最后输出结果为3 3 3 3

enum vs enum类

传统的enum,如果像下面这样定义:

enum Colors {Red,Green,Blue};enum OtherColors {Yellow,Blue};

编译器会报如下错误:

<source>:16:5: error: 'Blue' conflicts with a previous declaration16 |     Blue|     ^~~~
<source>:11:5: note: previous declaration 'Colors Blue'11 |     Blue|     ^~~~

为了解决这个问题,引入了enum class,如下:

enum class Colors {Red,Green,Blue};enum class OtherColors {Yellow,Blue};

modules

示例如下:

// Vector.h:

class Vector {public:Vector(int s);double& operator[](int i);int size();private:double∗ elem; // elem points to an array of sz doublesint sz;
};

// Vector.cpp:

#include "Vector.h" // get Vector’s interface
Vector::Vector(int s) :elem{new double[s]}, sz{s} {
}
double& Vector::operator[](int i) {return elem[i];
}
int Vector::size() {return sz;
}

// user.cpp

#include "Vector.h" // get Vector’s interface
#include <cmath> // get the standard-librar y math function interface including sqrt()
double sqrt_sum(Vector& v) {double sum = 0;for (int i=0; i!=v.siz e(); ++i)sum+=std::sqr t(v[i]); // sum of square rootsreturn sum;
}

最终格式如下:

图片

可以单独对user.cpp 和 Vector.cpp编译,生成.o文件,这是因为上述示例使用了#include操作,预处理器在遇到#include的时候,会将其中的内容完整的拷贝一份到相应的文件,这就导致每个.cpp都有头文件Vector.h的一个副本,代码体积膨胀不说,还增加了编译时间。

为了解决上述问题,引入了modules,使用module优化上述代码,如下:

// Vector.cpp

module;
export module Vector; // defining the module called "Vector"
export class Vector {public:Vector(int s);double& operator[](int i);int size();private:double∗ elem; // elem points to an array of sz doublesint sz;
};Vector::Vector(int s) :elem{new double[s]}, sz{s} {
}
double& Vector::operator[](int i) {
return elem[i];
}
int Vector::siz e() {
return sz;
}
expor t int size(const Vector& v) { return v.siz e(); }

// user.cpp

import Vector; // get Vector’s interface
#include <cmath> // get the standard-librar y math function interface including sqrt()
double sqrt_sum(Vector& v) {double sum = 0;for (int i=0; i!=v.siz e(); ++i)sum+=std::sqr t(v[i]); // sum of square rootsreturn sum;
}

对于这块的内容,可以详细阅读之前的文章:

未来已来:C++ modules初探

纯虚函数

如果其中一个成员函数使用= 0,那么该函数为纯虚函数,继承于存在纯虚函数的子类,其必须实现该函数:

class Base {public:void fun() = 0;
};class Derived : public Base {public:void fun() {}
}

如果声明一个存在纯虚函数的类,那边编译器会报错如下:

<source>:21:8: error: initializer specified for non-virtual method 'void Base::fun()'21 |   void fun() = 0;|        ^~~

派生

判断一个类是否继承于另外一个类,可以使用如下方式:

template<typename Base, typename T>
inline bool IsDerivedOf(T *ptr) {return dynamic_cast<Base*>(ptr) != nullptr;
}

智能指针

智能指针可以避免内存泄漏,此处文章较多,可以参考:

智能指针-使用、避坑和实现

一次诡异的内存泄漏

显式构造

对于如下这种:

class Vector {public:Vector(int sz);
}

可以使用Vector v = 3;这种方式进行初始化,往往这种并不是我们希望看到的,所以可以使用关键字explicit来强制显式初始化:

class Vector {public:explicit Vector(int sz);
}

move语义

自C++11起引入了move语义,不过这个很容易引起初学者的误解,其实move()本身并不做任何操作,其只是进行了简单的类型转换,而真正的移动操作需要类实现者进行定义。

STL对其定义如下:

template<typename _Tp>constexpr typename std::remove_reference<_Tp>::type&&move(_Tp&& __t) noexcept{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

如果需要深入了解其特性,可以参考文章:

【Modern C++】深入理解移动语义

CTAD

CTAD为Class Template Argument Deduction的缩写,中文称为类模板参数推导,在C++17之前,我们需要像下面这样写:

std::pair<int, double> p1 = {1, 3.41};

现在我们可以如下这样写:

std::pair              p2 = {1, 3.41};

可以参考文章【ModernCpp】新特性之CTAD

字面量

如果我们像下面这样写:

auto s = "hello";

s会被编译器推导为const char*,为了使得其为std::string类型,有以下几种方式:

auto s1 = std::string("hello");
std::string s2 = "hello";
auto s3 = "hello"s;

前两种方式比较常见,第三种方式是Modern cpp的新特性,俗称字面量。在这个语法中,"hello"是字符串字面值,而"s"是用户定义字面量的后缀,它将字符串字面值转换为std::string对象。

COW VS SSO

COW,想必大家都清楚其原理,这个机制很常用,比较常见的如fork等操作,在STL中也有用到这个,比如gcc5.1之前的string中,先看如下代码:

std::string s("str");std::string s1 = s;char *p = const_cast<char*>(s1.data());p[2] = '\0';std::cout << s << std::endl;std::cout << s1 << std::endl;

输出结果无非以下两种:

st
st

或者

str
st

第一种基于gcc5.1前的版本编译,第二种输出基于5.1之后的版本编译,这两个输出的不同正是源于gcc5.1之前的版本对于string的复制采用了COW操作。

自gcc5.1之后,字符串优化采用了新的机制,即SSO,其为Small String Optimization的简写,中文译为小字符串优化,基本原理是:当分配大小小于16个字节时候,从栈上进行分配,而如果大于等于16个字节,则在堆上进行内存分配

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/671903.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入解析 Spring 事务机制

当构建复杂的企业级应用程序时&#xff0c;数据一致性和可靠性是至关重要的。Spring 框架提供了强大而灵活的事务管理机制&#xff0c;成为开发者处理事务的首选工具。本文将深入探讨 Spring 事务的使用和原理&#xff0c;为大家提供全面的了解和实际应用的指导。 本文概览 首…

ORM模型类

模型 创建两个表 创建模型类 from django.db import models# Create your models here. class BookInfo(models.Model):name models.CharField(max_length10, uniqueTrue) # 书名pub_date models.DateField(nullTrue) # 发布时间read_count models.IntegerField(default…

【JSON2WEB】04 amis低代码前端框架介绍

1 什么是 amis amis 是一个低代码前端框架&#xff0c;它使用 JSON 配置来生成页面&#xff0c;可以减少页面开发工作量&#xff0c;极大提升效率。 看到amis一句话的介绍&#xff0c;感觉就是JSON2WEB要找的前端框架。 amis是百度开源的框架&#xff0c;毕竟是大厂&#xff0c…

即插即用、简单有效的大语言模型推荐算法!港大联合百度推出RLMRec

论文链接&#xff1a; https://arxiv.org/abs/2310.15950 论文代码&#xff1a; https://github.com/HKUDS/RLMRec 实验室主页&#xff1a; https://sites.google.com/view/chaoh/group-join-us?authuser0 TLDR 本文从互信息最大化的理论角度出发&#xff0c;通过引入文本信号…

使用No-SQL数据库支持连接查询用例的讨论

简介 在本文中&#xff0c;我们将简单介绍什么是No-SQL数据库。然后我们会讨论一种使用关系数据库比较容易实现的查询&#xff0c;即连接查询&#xff0c;怎么样使用No-SQL来实现。 什么是No-SQL数据库 与No-SQL数据库相对应的是传统的关系数据库&#xff08;RDBMS&#xff…

JRT监听程序

本次设计避免以往设计缺陷&#xff0c;老的主要为了保持兼容性&#xff0c;在用的设计就不好调了。 首先&#xff0c;接口抽象时候就不在给参数放仪器ID和处理类了&#xff0c;直接放仪器配置实体&#xff0c;接口实现想用什么属性就用什么属性&#xff0c;避免老方式要扩参数时…

java的excel列行合并模版

1.效果 2.模版 <tableborder"1"cellpadding"0"cellspacing"0"class"tablebor"id"TABLE"><tr align"center" class"bg217"><td style"background-color: #008000; color: #ffffff;p…

archlinux 使用 electron-ssr 代理 socks5

提前下载好 pacman 包 https://github.com/shadowsocksrr/electron-ssr/releases/download/v0.2.7/electron-ssr-0.2.7.pacman 首先要有 yay 和 aur 源&#xff0c;这个可以参考我之前的博客 虚拟机内使用 archinstall 安装 arch linux 2024.01.01 安装依赖 yay 安装的&#…

WebGL+Three.js入门与实战——绘制水平移动的点、通过鼠标控制绘制(点击绘制、移动绘制、模拟画笔)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

JVM 性能调优 - 常用的垃圾回收器(6)

垃圾收集器 在 JVM(Java虚拟机)中,垃圾收集器(Garbage Collector)是负责自动管理内存的组件。它的主要任务是在程序运行过程中,自动回收不再使用的对象所占用的内存空间,以便为新的对象提供足够的内存。 JVM中的垃圾收集器使用不同的算法和策略来实现垃圾收集过程,以…

第4章——深度学习入门(鱼书)

第4章 神经网络的学习 本章的主题是神经网络的学习。这里所说的“学习”是指从训练数据中自动获取最优权重参数的过程。本章中&#xff0c;为了使神经网络能进行学习&#xff0c;将导入损失函数这一指标。而学习的目的就是以该损失函数为基准&#xff0c;找出能使它的值达到最…

一些常见的电源方案

开关电源&#xff1a; RM C 板&#xff1a;&#xff08;24V电压&#xff0c;10A电流&#xff09; SMBJ30CA&#xff1a;静电和浪涌保护(TVS/ESD) 一般使用NMOS管&#xff0c;因为PMOS管导通电阻与NMOS管比较会较大 模电非基础01——从一种常见的防反接&#xff0c;上电缓启…

Mysql大表添加字段失败解决方案

背景 最近遇到一个问题&#xff0c;需要在user用户表千万级别数据中添加两个字段&#xff0c;发现老是加不上去&#xff0c;一直卡死。表数据量不仅大&#xff0c;而且是一个热点表&#xff0c;访问频率特别高&#xff0c;而且该表的访问是在一个大事务中。加字段的时候一直在…

挑战杯 python 爬虫与协同过滤的新闻推荐系统

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python 爬虫与协同过滤的新闻推荐系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&…

【人工智能】神奇的Embedding:文本变向量,大语言模型智慧密码解析(10)

什么是嵌入&#xff1f; OpenAI 的文本嵌入衡量文本字符串的相关性。嵌入通常用于&#xff1a; Search 搜索&#xff08;结果按与查询字符串的相关性排序&#xff09;Clustering 聚类&#xff08;文本字符串按相似性分组&#xff09;Recommendations 推荐&#xff08;推荐具有…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RichText组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之RichText组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、RichText组件 鸿蒙&#xff08;HarmonyOS&#xff09;富文本组件&#xff0c;…

【学习心得】Python好库推荐——tqdm

在很多时候&#xff0c;你都需要一个进度条来告知当前程序的运行状况和进展。tqdm 是一个在Python中广泛使用的命令行进度条工具库&#xff01;下面是这个库的主页&#xff1a;https://tqdm.github.io/ 一、快速入门 &#xff08;1&#xff09;for循环中 代码&#xff1a; …

句子嵌入: 交叉编码和重排序

这个系列目的是揭开嵌入的神秘面纱&#xff0c;并展示如何在你的项目中使用它们。第一篇博客介绍了如何使用和扩展开源嵌入模型&#xff0c;选择现有的模型&#xff0c;当前的评价方法&#xff0c;以及生态系统的发展状态。第二篇博客将会更一步深入嵌入并解释双向编码和交叉编…

C语言的起源

1940年代&#xff0c;最早的开始&#xff0c;编程语言是机器语言&#xff0c;用0/1表示的、计算机能直接识别和执行的一种机器指令的集合。最早的编程方式&#xff0c;就是给纸带打孔或者卡片机打孔。机器语言直接与硬件沟通&#xff0c;极具针对性&#xff0c;但是非常难于理解…

IP地址如何保护网络安全

面对网络攻击时&#xff0c;仅依靠常态化的网络安全防御系统已捉襟见肘&#xff0c;如联合使用IP地址数据可以形成多元化的安全解决方案&#xff0c;全面监控网络活动&#xff0c;发现潜在威胁&#xff0c;制定有针对性的应对措施。 网络攻击追踪 当网站或应用遭受DDoS等网络攻…