当前位置: 首页 > article >正文

Modern C++(一)基本概念

1、基本概念

1.1、注释

注释在翻译阶段3会被替换为单个空白字符从程序中移除

1.2、名字与标识符

标识符是一个由数字、下划线、大小写字符组成的任意长度序列。有效的标识符首个字符必须是以A-Z、a-z、下划线开头,。有效的标识符其他字符可以是0-9、A-Z、a-z、下划线。

标识符可以用来命名对象、引用、函数、枚举项、类型、类成员、命名空间、模板、模板特化、形参包(C++11 起)、goto 标号,以及其他实体。

1.3、类型

C++类型系统由以下类型组成:

  • 基础类型
    • void
    • std::nullptr_t
    • 算数类型
      • bool
      • 字符类型:char、signed char、unsigned char、char16_t、char32_t、wchar_t
      • 有符号整数类型:signed char、short int、int、long int、long long int
      • 无符号整数类型:
      • 浮点数类型:float、double、long double
  • 复合类型
    • 引用类型:
      • 左值引用类型
      • 右值引用类型
      • 指针类型
      • 指向成员的指针(成员指针)类型
      • 数组类型
      • 函数类型
      • 枚举类型(有/无作用域)
      • 类类型(非联合/联合体类型)

标量类型:标量类型变量一次仅存储一个值。算术类型、枚举类型、指针类型、成员指针类型、std::nullptr_t都是标量类型

1.3.1、隐式生存期类型

隐式生存期类型是C++20引入的概念,无需显式调用构造函数或使用new表达式,对象的生存期(lifetime)可以隐式开始。

普通生存期类型:

class Person {
public:Person(const std::string& name) : name_(name) {std::cout << "构造: " << name_.c_str() << std::endl;}~Person() {std::cout << "析构: " << name_.c_str() << std::endl;}std::string name_;
};int main()
{void *mem = malloc(sizeof(Person));// 未定义行为!必须先构造再使用// static_cast<Person*>(mem)->name_ = "Alice";Person* p = new (mem) Person("Alice");  // 调用构造函数p->~Person();  // 显式调用析构函数std::free(mem);  // 释放内存
}

隐式生存期类型:

struct Point {int x;int y;
};int main()
{void* memory = std::malloc(sizeof(Point));  // 分配内存// 可以直接使用,无需构造!Point* p = static_cast<Point*>(memory);p->x = 10;  // 合法:内存已被视为Point对象p->y = 20;free(memory); // 释放内存(自动析构,无需显式调用析构函数)
}

隐式生存期类型允许:直接操作未构造的内存,无需显式销毁对象,可直接覆盖内存。优点是预先分配大块内存(内存池),按需创建对象。避免频繁调用构造 / 析构函数,提升内存操作效率。

隐式生存期类型:

  • 标量类型
  • 结构体 / 类需满足:无用户定义的构造函数、析构函数。所有成员和基类都是隐式生存期类型。

1.3.2、静态类型

静态类型(Static Typing)是一种编程语言特性,它要求在编译时明确每个变量、表达式和函数的类型。

1.3.3、动态类型

动态类型(Dynamic Typing)是一个相对概念,主要指程序在运行时确定对象的实际类型,而非编译时。C++ 作为静态类型语言,其核心类型系统是静态的(编译时确定类型),有以下几个机制提供了有限的动态类型特性:

  • 多态:基类指针指向派生类对象
  • RTTI(运行时类型信息)

1.4、对象

1.4.1、对齐

每个对象类型都具有被称为对齐要求的性质,它是一个非负整数(类型是 std::size_t,总是 2 的幂),可以使用alignof和std::alignment_of查询类型的对齐要求,也可以使用alignas要求对齐数。

class Person {
public:Person(const std::string& name) : name_(name) {}
private:std::string name_;
};int main()
{cout << alignof(Person) << endl;cout << std::alignment_of<Person>::value << endl;
}

1.4.2、声明点

声明点(Point of Declaration)是一个编译期概念,它指定了标识符(如变量、函数、类等)在代码中正式生效的位置。

  • 对于变量和函数参数:声明点位于标识符名称之后,初始化表达式(如果有)之前
#include <iostream>int main(int argc, char **argv) {int x = 1;const int y = 2;{int x = x;      // 内部x的作用域在初始化器之前就开始了,所以内部x不能被外部x的值初始化std::cout << "x = " << x << std::endl;int y[y] = {};    // 内部y的作用域在y[y]之后,所以内部的y是一个包含2个int的数组}return 0;
}
  • 类和类模板,枚举的声明点位于该标识符之后:
struct S : public A{ // S 的作用域从冒号开始}enum E : int // E 的作用域从冒号开始,因此内部可以使用枚举类型E
{A = sizeof(E)
};
  • 类型别名或别名模板声明的声明点紧随该别名代表的类型标识之后
using T = int; // 外部 T 的作用域从分号开始
{using T = T*; // 内部 T 的作用域从分号开始,// 但分号前还在外部 T 的作用域中,// 因此等同于 T = int*
}
  • 对于函数:声明点位于函数名称之后,形参列表之前
void func(int x) {  // func的声明点在此处// 函数体中可使用func(如递归调用)
}

1.4.3、生存期

对象的生存期(Lifetime) 是指对象从创建(存储被分配且初始化完成)到销毁(存储被释放或重用)的时间段。理解对象生存期对于避免内存泄漏、悬空指针和资源管理至关重要。

生存期:当对象获取存储并初始化完成后生存期开始。对象的生存期在以下几个时刻结束:

  • 非类类型:销毁该对象时
  • 类类型:析构函数调用开始时
  • 对象占据的存储被释放,或者被其他对象重用
#include <iostream>class A {
public:A() {a = 10;}~A(){}void print() {std::cout << "A: a = "<< a << std::endl;}int a;
};class B {
public:int c;B() {c = 1;}
};void func() {A a;a.~A();new (&a) B;a.print();
}int main(int argc, char **argv) {func();std::cout << "test" << std::endl;return 0;
}

在上述代码func函数里,我们手动调用了a的析构函数,对象a的生命周期结束了,该对象占用的存储还在,但它已经不再是一个有效的对象,后续的print调用实际上时一个未定义的行为。

栈上的内存回收是由操作系统自动完成的,当对象的生命周期结束时,操作系统并不会立即将该对象所占用的内存标记为可用,而是等到整个栈帧(通常对应一个函数调用)结束时才会回收栈上的内存。因此,在对象的生命周期结束后,其所在的内存仍然存在,只是该内存已经不再属于一个有效的对象。

所以析构函数调用后,我们还可以重用a的内存。

生存期分类:

  • 自动生存期:局部变量(非static),从定义处开始,到离开作用域时结束。
  • 静态生存期:全局变量、static局部变量、static成员,从程序启动开始,到程序结束结束。
  • 动态生存期:通过new/new[]分配的对象,从new成功开始,到delete/delete[]结束。
  • 线程局部生存期:thread_local变量,与线程绑定(线程启动时开始,线程结束时结束)。

访问生存期外的对象 或者 重用存储前未结束生存期会导致未定义行为(UB)。

int* p = new int(10);
delete p;
*p = 20; // UB:p指向的对象已销毁struct S { ~S() {} };
S* s = new S;
new (s) S; // UB:原S的生存期未显式结束(需先调用析构)

1.5、声明与定义

声明(Declaration) 和 定义(Definition) 是两个核心概念,它们的区别直接影响代码的编译和链接过程。

1.5.1、声明

声明的主要作用是向编译器介绍某个标识符(如变量、函数、类等)的存在,告知编译器该标识符的名称、类型和一些基本属性,但并不为其分配内存或实现具体的功能。

声明的用途是解决编译时的符号引用。

以下情况是声明

  • 变量声明:用extern关键字且不带初始化器
extern const int a;
  • 类定义中的非 inline(C++17 起) 静态数据成员的声明
struct S
{int n;               // 定义 S::nstatic int i;        // 声明 S::iinline static int x; // 定义 S::x
};                       // 定义 S
int S::i;                // 定义 S::i
  • 函数声明:仅提供签名
void foo(int a);
  • 类/类型声明:
class MyClass;
enum Color : int;
  • typedef 声明,using 声明
typedef S S2;   // 声明但不定义 S2(S 可以是不完整类型)
using S2 = S;   // 声明但不定义 S2(S 可以是不完整类型)
using N::d;     // 声明,引入一个已存在的名称,所以N::d必须已经被声明

重要:声明可多次重复(同一作用域内允许多次声明),但是声明必须完全一致

extern int x;     // 声明1
extern double x;  // 错误:类型不一致

函数声明可能分散在多个头文件中,最终在源文件中定义

// utils.h
void helper();// math.h
void helper(); // 重复声明(合法)// utils.cpp
void helper() {} // 唯一定义

1.5.2、定义

定义是为标识符分配存储空间或提供完整实现。每个标识符必须有且仅有一个定义(One Definition Rule, ODR)。

定义的用途是解决链接时的具体实现。

  • 变量定义:
int x = 42; // 定义并初始化x(分配内存)
  • 函数定义
void foo(int a) { // 函数定义std::cout << a;
}
  • 类定义:完整描述成员和方法。
class MyClass {
public:void method() {}
};

相关文章:

Modern C++(一)基本概念

1、基本概念 1.1、注释 注释在翻译阶段3会被替换为单个空白字符从程序中移除 1.2、名字与标识符 标识符是一个由数字、下划线、大小写字符组成的任意长度序列。有效的标识符首个字符必须是以A-Z、a-z、下划线开头&#xff0c;。有效的标识符其他字符可以是0-9、A-Z、a-z、下…...

OpenCV图像旋转原理及示例

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 图像旋转是数字图像处理的一个非常重要的环节&#xff0c;是图像的几何变换手法之一。图像旋转算法是图像处理的基础算法。在数字图像处理过程中&#xff0c;经常要用到旋转&#xff0c;例如在进行图像扫描时…...

LLM Text2SQL NL2SQL 实战总结

目录 尽量全面的描述表的功能 尽量全面的描述字段的功能 适当放弃意义等价的字段 放弃业务上无用的字段 对于LLM来说,由于它没有什么行业经验,所以我们需要尽可能的给予它恰当的“背景信息”,才能使它更好的工作。所谓恰当,不是越多越好,因为太多的信息会消耗掉LLM的可…...

k8s 中使用 Service 访问时NetworkPolicy不生效问题排查

背景 针对一个服务如下NetworkPolicy, 表示只有n9e命名空间的POD才能访问 k8s-man 服务 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata:name: k8s-mannamespace: n9elabels:app: k8s-manversion: v1 spec:podSelector:matchLabels:app: k8s-manversion: v1…...

【实战篇】数字化打印——打印部署管理接口开发

前言 前面的章节已经介绍了打印管理模块的主要界面设计&#xff0c;本篇介绍用myBuilder开发界面接口&#xff0c;实现最终的功能。 1. 配置打印应用菜单 首先配置挂载好模块菜单 让菜单点击能访问到对应的页面 2. 打印部署管理数据表详细设计 以下是打印部署管理的数据表字…...

MacOS Python3安装

python一般在Mac上会自带&#xff0c;但是大多都是python2。 python2和python3并不存在上下版本兼容的情况&#xff0c;所以python2和python3可以同时安装在一台设备上&#xff0c;并且python3的一些语法和python2并不互通。 所以在Mac电脑上即使有自带python&#xff0c;想要使…...

磁盘I/O瓶颈排查:面试通关“三部曲”心法

想象一下&#xff0c;你就是线上系统的“交通调度总指挥”&#xff0c;服务器的磁盘是所有数据进出的“核心枢纽港口”。当这个“港口”突然拥堵不堪&#xff0c;卡车&#xff08;数据请求&#xff09;排起长龙&#xff0c;进不去也出不来&#xff0c;整个系统的“物流”&#…...

idea启动报错:java: 警告: 源发行版 11 需要目标发行版 11(亲测解决)

引起原因 idea的jdk没有替换干净 1.配置project file–Project Structrue–Project 2.配置Modules-Sources file–Project Structrue–Modules-Sources 改为jdk11 3.配置Modules-Dependencies file–Project Structrue–Modules-Dependencies...

树莓派4 yolo 11l.pt性能优化后的版本

树莓派4 使用 Picamera2 拍摄图像&#xff0c;然后通过 YOLO11l.pt 进行目标检测&#xff0c;并在实时视频流中显示结果。但当前的代码在运行时可能会比较卡顿&#xff0c;主要原因包括&#xff1a; picam2.capture_array() 是一个较慢的操作&#xff1b;YOLO 推理可能耗时较长…...

鸿蒙OSUniApp开发支持多语言的国际化组件#三方框架 #Uniapp

使用UniApp开发支持多语言的国际化组件 在全球化的今天&#xff0c;一个优秀的应用往往需要支持多种语言以满足不同地区用户的需求。本文将详细讲解如何在UniApp框架中实现一套完整的国际化解决方案&#xff0c;从而轻松实现多语言切换功能。 前言 去年接手了一个面向国际市场…...

国产数据库工具突围:SQLynx如何解决Navicat的三大痛点?深度体验报告

引言&#xff1a;Navicat的"中国困境" 当开发者面对达梦数据库的存储过程调试&#xff0c;或是在人大金仓中处理复杂查询时&#xff0c;Navicat突然变得力不从心——这不是个例。 真实痛点&#xff1a;某政务系统迁移至OceanBase后&#xff0c;开发团队发现Navicat无…...

《Adversarial Sticker: A Stealthy Attack Method in the Physical World》论文分享(侵删)

原文链接&#xff1a;Adversarial Sticker: A Stealthy Attack Method in the Physical World | IEEE Journals & Magazine | IEEE Xplore author{Xingxing Wei and Ying Guo and Jie Yu} 摘要 为了评估深度学习在物理世界中的脆弱性&#xff0c;最近的工作引入了对抗补丁…...

Python生成器:高效处理大数据的秘密武器

生成器概述 生成器是 Python 中的一种特殊迭代器&#xff0c;通过普通函数的语法实现&#xff0c;但使用 yield 语句返回数据。生成器自动实现了 __iter__() 和 __next__() 方法&#xff0c;因此可以直接用于迭代。生成器的核心特点是延迟计算&#xff08;lazy evaluation&…...

React Native/Flutter 原生模块开发

以下是关于 React Native 和 Flutter 原生模块开发的基本知识点总结: 一、核心概念对比 维度React NativeFlutter架构基础JavaScriptCore/Hermes + Bridge/TurboModulesDart VM + Skia引擎原生交互方式Native Modules + Native UI ComponentsPlatform Channels + Platform Vie…...

嵌入式STM32学习——继电器

继电器模块引脚说明 VCC&#xff08;&#xff09;&#xff1a; 供电正极。连接此引脚到电源&#xff08;通常是直流电源&#xff09;&#xff0c;以提供继电器线圈所需的电流。 GND&#xff08;-&#xff09;&#xff1a; 地。连接此引脚到电源的负极或地。 IN&#xff08;或…...

从基础到实习项目:C++后端开发学习指南

在当今技术快速迭代的背景下&#xff0c;后端开发作为软件工程的核心支柱持续发挥着关键作用。C凭借其卓越的性能表现和系统级控制能力&#xff0c;依然是构建高性能后端服务的首选语言之一。本文将系统性地解析现代C后端开发的核心技术体系&#xff0c;包括从语言特性精要到架…...

AI软件汇总与功能解析:赋能未来的智能工具库

人工智能&#xff08;AI&#xff09;技术的快速发展催生了大量功能强大的软件工具&#xff0c;覆盖自然语言处理、计算机视觉、数据分析、自动化决策等多个领域。本文将汇总当前主流的AI软件&#xff0c;并解析其核心功能与应用场景&#xff0c;为企业和开发者提供参考指南。 一…...

Xinference推理框架

概述 GitHub&#xff0c;官方文档。 核心优势 性能优化&#xff1a;通过vLLM、SGLang等引擎实现低延迟推理&#xff0c;吞吐量提升2-3倍&#xff1b;企业级支持&#xff1a;支持分布式部署、国产硬件适配及模型全生命周期管理&#xff1b;生态兼容&#xff1a;无缝对接LangC…...

前端ECS简介

ECS概念 ECS是一种软件架构模式&#xff0c;常见于游戏业务场景&#xff0c;其主要对象分类为 • Entity 实体,ECS架构中所有的业务对象都必须拥有一个唯一的Entity实体 • Component 组件,存储着数据结构,对应着某一种业务属性,一个Entity上可以动态挂载多个Component • …...

ET ProcessOuterSender类(实体) 分析

ProcessOuterSender 夸进程发送Actor消息&#xff0c;只在NetInner(Scene)使用。 字段 TIMEOUT_TIME RPC超时时间RpcId rpcIdrequestCallback 存储RPC的回调事件AService 进程之间的网络服务InnerProtocol 内部网络协议类型 目前固定KCP 方法 OnRead 方法&#xff0c;收包…...

redis中key的过期和淘汰

一、过期&#xff08;redis主动删除&#xff09; 设置了ttl过期时间的key&#xff0c;在ttl时间到的时候redis会删除过期的key。但是redis是惰性过期。惰性过期&#xff1a;redis并不会立即删除过期的key&#xff0c;而是会在获取key的时候判断key是否过期&#xff0c;如果发现…...

Dify与n8n全面对比指南:AI应用开发与工作流自动化平台选择【2025最新】

Dify与n8n全面对比指南&#xff1a;AI应用开发与工作流自动化平台选择【2025最新】 随着AI技术与自动化工具的迅速发展&#xff0c;开发者和企业面临着多种平台选择。Dify和n8n作为两个备受关注的自动化平台&#xff0c;分别专注于不同领域&#xff1a;Dify主要面向AI应用开发&…...

【深度学习之四】知识蒸馏综述提炼

知识蒸馏综述提炼 目录 知识蒸馏综述提炼 前言 参考文献 一、什么是知识蒸馏&#xff1f; 二、为什么要知识蒸馏&#xff1f; 三、一点点理论 四、知识蒸馏代码 总结 前言 知识蒸馏作为一种新兴的、通用的模型压缩和迁移学习架构&#xff0c;在最近几年展现出蓬勃的活力…...

redis解决常见的秒杀问题

title: redis解决常见的秒杀问题 date: 2025-03-07 14:24:13 tags: redis categories: redis的应用 秒杀问题 每个店铺都可以发布优惠券&#xff0c;保存到 tb_voucher 表中&#xff1b;当用户抢购时&#xff0c;生成订单并保存到 tb_voucher_order 表中。 订单表如果使用数据…...

TypeScript中文文档

最近一直想学习TypeScript&#xff0c;一直找不到一个全面的完整的TypeScript 中文文档。在网直上找了了久&#xff0c;终于找到一个全面的中文的typescript中文学习站&#xff0c;有学习ts的朋友可以年。 文档地址&#xff1a;https://typescript.uihtm.com 该TypeScript 官…...

Function Calling

在介绍Function Calling之前我们先了解一个概念,接口。 接口 两种常见接口: 人机交互接口,User Interface,简称 UI应用程序编程接口,Application Programming Interface,简称 API接口能「通」的关键,是两边都要遵守约定。 人要按照 UI 的设计来操作。UI 的设计要符合人…...

【搭建Node-RED + MQTT Broker实现AI大模型交互】

搭建Node-RED MQTT Broker实现AI大模型交互 搭建Node-RED MQTT Broker实现AI大模型交互一、系统架构二、环境准备与安装1. 安装Node.js2. 安装Mosquitto MQTT Broker3. 配置Mosquitto4. 安装Node-RED5. 配置Node-RED监听所有网络接口6. 启动Node-RED 三、Node-RED流程配置1. …...

高可靠低纹波国产4644电源芯片在工业设备的应用

摘要 随着工业自动化和智能化的飞速发展&#xff0c;工业设备对于电源芯片的性能和可靠性提出了前所未有的严格要求。电源芯片作为工业设备的核心供电组件&#xff0c;其性能直接影响到整个设备的运行效率和稳定性。本文以国科安芯的ASP4644四通道降压稳压器为例&#xff0c;通…...

面试--HTML

1.src和href的区别 总结来说&#xff1a; <font style"color:rgb(238, 39, 70);background-color:rgb(249, 241, 219);">src</font>用于替换当前元素&#xff0c;指向的资源会嵌入到文档中&#xff0c;例如脚本、图像、框架等。<font style"co…...

SparkSQL操作Mysql-准备mysql环境

我们计划在hadoop001这台设备上安装mysql服务器&#xff0c;&#xff08;当然也可以重新使用一台全新的虚拟机&#xff09;。 以下是具体步骤&#xff1a; 使用finalshell连接hadoop001.查看是否已安装MySQL。命令是: rpm -qa|grep mariadb若已安装&#xff0c;需要先做卸载MyS…...