CMake笔记

CMake笔记

文章目录

  • CMake笔记
  • 1 工程项目一般形式
  • 2 常见命令
    • 2.1 project
    • 2.2 set
    • 2.3 message
    • 2.4 add_executable()
    • 2.5 语法原则
    • 2.6 add_subdirectory
    • 2.7 add_library
    • 2.8 list
  • 3 安装
    • 3.1 安装.h文件/文本文件
    • 3.2 安装工程脚本
    • 3.3 安装目录/目录下内容
    • 3.4 安装库文件
    • 3.5安装过程
  • 4 静态库和动态库
    • 4.1 同时构建静态库和动态库
    • 4.2 安装头文件.h和库.a/.so
      • 4.2.1 安装过程
      • 4.2.2 使用外部共享库和头文件
      • 4.2.3 使用find_package()来找到自定义库
  • 5 find_package()
    • 5.1 find_package中的xxx是什么?
    • 5.2 使用find_package命令就是为了找到头文件和库文件位置
    • 5.3 find_path
    • 5.4 find_library
  • 6 target_link_libraries(库文件LIBRARIES)
  • 7 include_directories()

1 工程项目一般形式

  1. 建立build文件夹
mkdir build
  1. 进入build文件
cd build
  1. cmake生成makefile文件
cmake ..   # cmake是对CMakeLists.txt操作,操作命令要在同一文件夹
  1. make编译
make    # make是对Makefile操作
  1. 调用
./useHello   # 这里是调用build文件夹下的helloSLAM
cmake会自己找.h文件  如果.h不在当前文件夹,需要加上include_directories(文件名)
若.cpp也不在当前文件,在库文件哪里也加上路径
# 声明要求的 cmake 最低版本
cmake_minimum_required(VERSION 2.8)include_directories("include")
# 声明一个 cmake 工程
project(HelloSLAM)# 设置编译模式
set(CMAKE_BUILD_TYPE "Debug")# 添加hello库   静态库
add_library(hello_shared ./src/libHelloSLAM.cpp)
# 共享库    动态库
add_library(hello_shared SHARED ./src/libHelloSLAM.cpp)# 添加可执行程序调用hello库中函数
# 语法:add_executable( 程序名 源代码文件 )
add_executable(useHello ./src/useHello.cpp)# 将库文件链接到可执行程序上
target_link_libraries(useHello hello_shared)

在这里插入图片描述

在这里插入图片描述

2 常见命令

2.1 project

PROJECT(projectname [CXX] [C] [Java])   #项目名 以及支持的语言   默认支持所有的语言
  • 创建项目指令project默认创建了一下两个cmake变量
<projectname>_BINARY_DIR     # 内部编译!!!
<projectname>_SOURCE_DIR# 可以用message输出查看,在cmake在编译CMakeLists.txt时候就会输出对应的信息
message(STATUS "this is a binary dir" <projectname>_BINARY_DIR)
  • 系统预定义的两个变量,修改工程名不会影响这两个变量的值!
 PROJECT_BINARY_DIR    # (make)编译路径PROJECT_SOURCE_DIR    # 工程(源文件)路径
  • 实验
project(Hello CXX)
message(STATUS "this is binary dir" ${Hello_BINARY_DIR})
# 等价 message(STATUS "this is binary dir" ${PORECT_BINARY_DIR})
message(STATUS "this is source  dir" ${Hello_SOURCE_DIR})
# 等价 message(STATUS "this is source  dir" ${PROJECT_SOURCE_DIR})
add_executable(hello hello.cpp)

2.2 set

  • 用来设置指定变量的一个替换变量
SET(SRC_LIST main.cpp)     # SRC_LIST变量就代表了main.cpp
SET(SRC_LIST main.cpp t1.cpp t2.cpp)   # SRC_LIST变量就代表了main.cpp  t1.cpp t2.cpp
  • 其它的一些变量设置
# 设置CMake预定义的内建变量
set(CMAKE_CXX_FLAGS "-O3")   # 优化选项,告诉编译器优化我们的代码
set(CMAKE_CXX_FLAGS "-std = c++11")   # 设置为c++11标准# 设置编译模式
set(CMAKE_BUILD_TYPE "Debug")   # 占用空间比较大,可以debug
set(CMAKE_BUILD_TYPE "Release") # 占用空间比较小
  • 实验1:利用变量cc来替换Hello.cpp
project(Hello CXX)
set(CC hello.cpp)
add_executable(hello CC)

2.3 message

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR]  "message to display" ...)
  • SEND_ERROR,产生错误,生成过程被跳过。
  • STATUS ,输出前缀是一个 — 的信息。
  • FATAL_ERROR,立即终止所有cmake 过程.

上面三种选择一种,引号用来解释要输出的信息,三个点表示对应的变量

MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})

2.4 add_executable()

ADD_EXECUTABLE(hello ${SRC_LIST})     # 生成的可执行文件名是hello# 源文件读取变量SRC_LIST中的内容
ADD_EXECUTABLE(hello main.cpp)        # 这两句是等价的。									  

2.5 语法原则

  • 变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名

  • 指令(参数 1 参数 2…) 参数使用括弧括起,参数之间使用空格或封号分开。

  • 指令是大小写无关的,参数和变量是大小写相关的。

2.6 add_subdirectory

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])# source_dir  用于向当前工程添加存放  源文件 的子目录
# [binary_dir]   指定(子目录里面生成的可执行文件)中间二进制和目标二进制存放的位置
# EXCLUDE_FROM_ALL 参数的含义是将这个目录从编译过程中排除
  • 实验验证

​ 首先改写SLAM第三讲中的CMakeLists.txt文件,指定可执行文件的位置(build/…)。

cmake_minimum_required(VERSION 2.8)
project(chapter3)
set(CMAKE_CXX_FLAGS "-std=c++11")add_subdirectory(useEigen useEigen)add_subdirectory(useGeometry useGeometry)add_subdirectory(visualizeGeometry visualizeGeometry) add_subdirectory(examples examples)

在这里插入图片描述

编译之后,其可执行文件都被保存在了build/…与定义的路径下面

在这里插入图片描述

比如

在这里插入图片描述

在这里插入图片描述

相反,如果我们不设置其可执行文件的输出位置,默认在最外层build/建立和项目名一致的文件夹

cmake_minimum_required(VERSION 2.8)
project(chapter3)
set(CMAKE_CXX_FLAGS "-std=c++11")add_subdirectory(useEigen ./cc)add_subdirectory(useGeometry)add_subdirectory(visualizeGeometry) add_subdirectory(examples)

在这里插入图片描述

2.7 add_library

ADD_LIBRARY(hello  SHARED  ${LIBHELLO_SRC})
  • hello:就是正常的库名,生成的名字前面会加上lib,最终产生的文件是libhello.so
  • SHARED,动态库 STATIC,静态库
  • ${LIBHELLO_SRC} :源文件,比如自己写的hello.cpp

2.8 list

set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" )
list( APPEND CMAKE_MODULE_PATH "${CMAKE_ROOT}/Modules" ) 
# 表示将后面的 "" 里面的内容添加到CMAKE_MODULE_PATH列表里

3 安装

install安装可以包括:二进制、动态库、静态库以及文件、目录、脚本等。测试样例在主目录下CMake下面test1.

.
├── build
├── CMakeLists.txt
├── COPYRIGHT    # 版权
├── doc          # 目录
│   └── hello.txt
├── README       # 帮助文档
├── runhello.sh
└── src├── CMakeLists.txt└── hello.cpp3 directories : build,doc,src      7 files : ...

3.1 安装.h文件/文本文件

project(Hello)
add_subdirectory(src bin)# 安装文件FILES(上面创建的COPYRIGHT和README)    share/doc/cmake/是安装路径
install(FILES COPYRIGHT README DESTINATION share/doc/cmake/)  # 也可以安装头文件.h   见4.2
install(FILES hello.h DESTINATION include/hello)

参数1:DESTINATION

DESTINATION   # destination 目的地  即安装的路径
1、写绝对路径
2、可以写相对路径,相对路径实际路径是:${CMAKE_INSTALL_PREFIX}/<DESTINATION 定义的路径>CMAKE_INSTALL_PREFIX  默认是在 /usr/local/cmake -DCMAKE_INSTALL_PREFIX=/usr    在cmake的时候指定CMAKE_INSTALL_PREFIX变量的路径

3.2 安装工程脚本

project(Hello)
add_subdirectory(src bin)
# 2.安装工程脚本PROGRAMS   实际路径: /usr/local/bin
install(PROGRAMS test.sh DESTINATION bin)	

参数2:PROGRAMS非目标文件的可执行程序安装(比如脚本之类)

3.3 安装目录/目录下内容

project(Hello)
add_subdirectory(src bin)# DIRECTORY  3.安装目录下内容hello.txt			因为doc后面加了/
# DIRECTORY 后面连接的是所在 Source 目录的相对路径
install(DIRECTORY doc/ DESTINATION share/doc/cmake)	

参数3:doc/

目录名不以/结尾:这个 目录 将被安装为目标路径下的

目录名以/结尾:将这个 目录中的内容 安装到目标路径

3.4 安装库文件

project(Hello)
add_subdirectory(src bin)
# 4 安装库文件  见4.2
# 二进制,静态库,动态库安装都用TARGETS
# ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME 特指可执行目标二进制。
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)

3.5安装过程

pj@p:~/slambook/CMake/build$ camke ..pj@p:~/slambook/CMake/build$ make -j4
[ 50%] Building CXX object bin/CMakeFiles/hello.dir/main.o
[100%] Linking CXX executable hello
[100%] Built target hellopj@p:~/slambook/CMake/build$ sudo make install    # 这里才开始安装install
[100%] Built target hello
Install the project...
-- Install configuration: ""
-- Up-to-date: /usr/local/share/doc/cmake/COPYRIGHT
-- Up-to-date: /usr/local/share/doc/cmake/README
-- Installing: /usr/local/bin/test.sh
-- Up-to-date: /usr/local/share/doc/cmake
-- Installing: /usr/local/share/doc/cmake/test_cmake.txt

这里很重要,因为有些安装包你下载的地方不是默认的地方,把它cmake编译之后,还要将其加入的默认路径 /usr/local/...

4 静态库和动态库

静态库和动态库的区别

  • 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”
  • 静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行
  • 动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行。

测试样例于cmake/test2

4.1 同时构建静态库和动态库

​ 先构建如下文件

pj@p:~/CMake/test2$ tree
.
├── build
├── CMakeLists.txt
└── lib├── CMakeLists.txt├── hello.cpp└── hello.h2 directories, 4 files

hello.h中的内容

#ifndef HELLO_H
#define Hello_Hvoid HelloFunc();#endif

hello.cpp中的内容

#include "hello.h"
#include <iostream>
void HelloFunc(){std::cout << "Hello World" << std::endl;
}

项目中的cmake内容

PROJECT(HELLO)
ADD_SUBDIRECTORY(lib bin)

​ 下面这种方法不能同时构建,只会生成一中类型的库

# 如果用这种方式,只会构建一个动态库,不会构建出静态库,虽然静态库的后缀是.a
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})# 修改静态库的名字,这样是可以的,但是我们往往希望他们的名字是相同的,只是后缀不同而已
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
  • SET_TARGET_PROPERTIES

​ 这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本,同时构建静态和动态库。lib下cmakelists.txt内容如下。

SET(LIBHELLO_SRC hello.cpp)ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})# 对hello_static的重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES  OUTPUT_NAME "hello")
# cmake 在构建一个新的target 时,会尝试清理掉其他使用这个名字的库,因为,在构建 libhello.so 时, 就会清理掉 libhello.a
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)  # 清除ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})SET_TARGET_PROPERTIES(hello PROPERTIES  OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)

4.2 安装头文件.h和库.a/.so

​ 我们将 hello 的共享库安装到/lib目录,将 hello.h 安装到/include/hello 目录

SET(LIBHELLO_SRC hello.cpp)ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})# 对hello_static的重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES  OUTPUT_NAME "hello")
# cmake 在构建一个新的target 时,会尝试清理掉其他使用这个名字的库,因为,在构建 libhello.so 时, 就会清理掉 libhello.a
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)  # 清除ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})SET_TARGET_PROPERTIES(hello PROPERTIES  OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)# 文件放到该目录下
INSTALL(FILES hello.h DESTINATION include/hello)# 二进制,静态库,动态库安装都用TARGETS
# ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME 特指可执行目标二进制。
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)

4.2.1 安装过程

pj@p:~/CMake/test2/build$ cmake -D CMAKE_INSTALL_PREFIX=/usr .. pj@p:~/CMake/test2/build$ make
[ 25%] Building CXX object bin/CMakeFiles/hello_static.dir/hello.o
[ 50%] Linking CXX static library libhello.a
[ 50%] Built target hello_static
[ 75%] Building CXX object bin/CMakeFiles/hello.dir/hello.o
[100%] Linking CXX shared library libhello.so
[100%] Built target hellopj@p:~/CMake/test2/build$ sudo make install   # 更改默认路径
Consolidate compiler generated dependencies of target hello_static
[ 50%] Built target hello_static
Consolidate compiler generated dependencies of target hello
[100%] Built target hello
Install the project...
-- Install configuration: ""
-- Installing: /usr/include/hello/hello.h
-- Installing: /usr/lib/libhello.so
-- Installing: /usr/lib/libhello.a

结果

在这里插入图片描述

4.2.2 使用外部共享库和头文件

准备工作,新建一个目录来使用外部共享库和头文件(使用上面安装的库)

[root@MiWiFi-R4CM-srv cmake3]# tree
.
├── build
├── CMakeLists.txt
└── src├── CMakeLists.txt└── main.cpp
  • CMakeLists.txt
project(hello)add_subdirectory(src bin)
  • main.cpp
#include <hello.h>int main(){HelloFunc();
}
  • src下的CMakeLists.txt

include_directories("/usr/include/hello")   # 链接头文件  .h
add_executable(test main.cpp)target_link_libraries(test /usr/lib/libhello.so)  # 链接库文件  .cpp  libhello.so也可

4.2.3 使用find_package()来找到自定义库

  • FindHELLO.cmake
find_path(HELLO_INCLUDE_DIR hello.h /usr/include/hello)
find_library(HELLO_LIBRARY NAMES libhello.so PATHS /usr/lib )
if (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)set(HELLO_FOUND TRUE)endif (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)

写在最外层CMakeLists.txt

在这里插入图片描述

cmake_minimum_required(VERSION 3.22)project(hello)## set(CMAKE_MODULE_PATH "../cmake")   这里可以写绝对路径,然后可以分子项目,具体见test4
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")add_executable(test main.cpp)find_package(HELLO)message(STATUS "HELLO_INCLUDE_DIRS " ${HELLO_INCLUDE_DIR} )
message(STATUS " HELLO_LIBRARY " ${HELLO_LIBRARY} )if(HELLO_FOUND)target_include_directories(test PRIVATE ${HELLO_INCLUDE_DIR})target_link_libraries(test ${HELLO_LIBRARY})  # 链接库文件  .cpp  libhello.so也可
else(HELLO_FOUND)message(FATAL_ERROR "HELLO library not found")
endif(HELLO_FOUND)

如果分为子项目,即最外层只写

cmake_minimum_required(VERSION 3.22)
project(hello)
add_subdirectory(src bin)

在这里插入图片描述

和上面的cmakelists相同,只需要改一句

set(CMAKE_MODULE_PATH "../cmake")   # 这里可以写绝对路径,然后可以分子项目,具体见test4

在这里插入图片描述

5 find_package()

find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE][REQUIRED] [[COMPONENTS] [components...]][OPTIONAL_COMPONENTS components...][REGISTRY_VIEW  (64|32|64_32|32_64|HOST|TARGET|BOTH)][GLOBAL][NO_POLICY_SCOPE][BYPASS_PROVIDER])
${XXX_INCLUDE_DIRS}    ## 一般要查找这两个变量,即头文件与源文件位置
${XXX_LIBRARIES}
find_package(Pangolin REQUIRED)          # 查找Pangolin库,REQUIRED指找不到就在此停止程序。
include_directories(${Pangolin_INCLUDE_DIRS})  # Pangolin库的头文件
add_executable(plotTrajectory plotTrajectory.cpp)
target_link_libraries(plotTrajectory ${Pangolin_LIBRARIES})   # 链接Pangolin的源文件,库

5.1 find_package中的xxx是什么?

# locate 库名 | grep cmake     xxx就是Config前面那个名字
locate sophus | grep cmake
locate Pangolin | grep cmake

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.2 使用find_package命令就是为了找到头文件和库文件位置

include_directories(${XXX_INCLUDE_DIRS})   # 目的就是链接
target_link_libraries(x ${XXX_LIBRARIES}) # 这种方法是可行的,比如Pangolin库是没问题的find_package(Pangolin REQUIRED)          # 查找Pangolin库,REQUIRED指找不到就在此停止程序。
include_directories(${Pangolin_INCLUDE_DIRS})  # Pangolin库的头文件
add_executable(plotTrajectory plotTrajectory.cpp)
target_link_libraries(plotTrajectory ${Pangolin_LIBRARIES})   # 链接Pangolin的源文件,库

但是,sophus这个库直接加这两个路径是不行的。我们可以载程序中使用message查看信息,它输出的是空白!

message(STATUS "Sophus_INCLUDE_DIRS"  ${Sophus_INCLUDE_DIRS})
message(STATUS "Sophus_INCLUDE_DIRS"  ${Sophus_LIBRARIES})

在这里插入图片描述

实际上我们已经安装了sophus的,并且它确实不能找到(以这种方式)

在这里插入图片描述

  • 解决上述问题的办法
# 1. 直接将绝对路径赋给它
include_directories(/usr/local/include/sophus)
# 2.  Sophus::Sophus 
target_link_libraries(useSophus Sophus::Sophus)

解释一下第二种方法的原因,

在这里插入图片描述

我们打开那个SophusTargets.cmake,里面有部分内容如下。就是可以把Sophus理解为一个类,对象,通过::来导入库。

# Create imported target Sophus::Sophus
add_library(Sophus::Sophus INTERFACE IMPORTED)

之所以不能用${Sophus_INCLUDE_DIRS}),是因为在Config.cmake文件种没有这个东西。

在这里插入图片描述

但是eigen里面就有,所以eigen可以使用那种方式来链接库,eigen由头文件组成,没有库文件

在这里插入图片描述

5.3 find_path

find_path(myCeres NAMES ceress.h PATHS /ceres/include/ceres NO_DEFAULT_PATH)
include_directories(${myCeres})# eg   hello.h为要找的头文件    /usr/include/hello为绝对路径
find_path(HELLO_INCLUDE_DIR hello.h /usr/include/hello)

5.4 find_library

find_library (<VAR> name [path1 path2 ...])    #<VAR> 找到的库的变量名(全路径)
# eg   NAMES是指要找的动态库的名字  PATHS指我们为出现提供的路径,可以有多个
find_library(HELLO_LIBRARY NAMES libhello.so PATHS /usr/lib )message(STATUS "HELLO_INCLUDE_DIRS " ${HELLO_INCLUDE_DIR} )
message(STATUS " HELLO_LIBRARY " ${HELLO_LIBRARY} )

6 target_link_libraries(库文件LIBRARIES)

# 这里要说的是,item可以库文件
target_link_libraries(plotTrajectory ${Pangolin_LIBRARIES}) # item可以是路径
target_link_libraries(useHello ./src/libHelloSLAM.cpp) # item可以是target,就是上面我们locate xx | grep cmake 找的东西
# 而且,一旦有这个东西,那么用例如这样形式  Sophus::Sophus  我们就不需要include加头文件、库文件等
target_link_libraries(useSophus Sophus::Sophus)

7 include_directories()

​ 这里想补充以下关于include_directories()的用法,用于指定头文件的搜索路径,方便编译器查找相应的头文件。

#include <pangolin/pangolin.h>   // 比如说我们要调用eigen库和pangolin库
#include <Eigen/Core>

查看库的路径

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

AI大模型,掀起新一波智能浪潮!

AI大模型的出现&#xff0c;标志着人工智能技术迈入了一个新的阶段。这些巨大的模型不仅在规模上超越了以往任何其他人工智能系统&#xff0c;而且在性能上也取得了巨大的突破。由于其庞大的参数量和复杂的结构&#xff0c;AI大模型在各个领域展现出了强大的学习能力和推理能力…

434G数据失窃!亚信安全发布《勒索家族和勒索事件监控报告》

最新态势快速感知 最新一周全球共监测到勒索事件90起&#xff0c;与上周相比数量有所增加。 lockbit3.0仍然是影响最严重的勒索家族&#xff1b;alphv和cactus恶意家族也是两个活动频繁的恶意家族&#xff0c;需要注意防范。 Change Healthcare - Optum - UnitedHealth遭受了…

一条SQL引起的系统不可用

一.前言 最近在运维系统&#xff0c;系统对客端突然报了403错误&#xff0c;从后台看发现了大量的慢SQL&#xff0c;导致查询超时&#xff0c;仔细分析我从来没见过那么厚颜无耻的SQL&#xff0c;一条SQL语句关联了一个大表&#xff08;6000数据&#xff09;查询了10次。我也很…

2024年第二届智能制造与自动化前沿国际会议 | Ei、Scopus双检索

会议简介 Brief Introduction 2024年第二届智能制造与自动化前沿国际会议&#xff08;CFIMA 2024&#xff09; 会议时间&#xff1a;2024年8月23 -25日 召开地点&#xff1a;中国包头 大会官网&#xff1a;www.cfima.org 随着全球新一轮科技革命和产业变革突飞猛进&#xff0c;…

LeetCode 刷题 [C++] 第3题.无重复字符的最长子串

题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 题目分析 可以使用滑动窗口加哈希表来实现&#xff1a; 使用start和end两个变脸来表示滑动窗口的头部位置和尾部位置&#xff0c;两者开始均为0&#xff1b;借助哈希表来记录已经遍…

JVM(类加载机制)

类加载就是 .class 文件, 从文件(硬盘) 被加载到内存(元数据区)中的过程 类加载的过程 加载: 找 .class 文件的过程, 打开文件, 读文件, 把文件读到内存中 验证: 检查 .class 文件的格式是否正确 .class 是一个二进制文件, 其格式有严格的说明 准备: 给类对象分配内存空间 (先在…

专业140+总430+电子科技大学858信号与系统考研经验成电电子信息与通信工程,电科大,真题,大纲,参考书。

今年考研成绩出来&#xff0c;初试专业课858信号与系统140&#xff0c;总分430&#xff0c;其余各门分数都比较平稳&#xff0c;总分好于自己估分&#xff0c;应群里很多同学要求&#xff0c;我总结一下自己的复习经验。首先我是一个大冤种&#xff0c;专业课资料学长给了一套&…

uniapp实现---类似购物车全选

目录 一、实现思路 二、实现步骤 ①view部分展示 ②JavaScript 内容 ③css中样式展示 三、效果展示 四、小结 注意事项 一、实现思路 点击商家复选框&#xff0c;可选中当前商家下的所有商品。点击全选&#xff0c;选中全部商家的商品 添加单个多选框&#xff0c;在将多选…

react tab选项卡吸顶实现

react tab选项卡吸顶实现&#xff0c;直接上代码&#xff08;代码有注释&#xff09; tsx代码 /* eslint-disable react-hooks/exhaustive-deps */ import React, { useEffect, useState } from "react"; import DocumentTitle from react-document-title import s…

UE5中实现后处理深度描边

后处理深度描边可以通过取得边缘深度变化大的区域进行描边&#xff0c;一方面可以用来做角色的等距内描边&#xff0c;避免了菲尼尔边缘光不整齐的问题&#xff0c;另一方面可以结合场景扫描等特效使用&#xff0c;达到更丰富的效果&#xff1a; 后来解决了开启TAA十字线和锯齿…

Java零基础 - 数组的定义和声明

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

AI预测福彩3D第4弹【2024年3月7日预测】

经过前面几次的预测&#xff0c;7码命中率已经有了明显提高&#xff0c;今天&#xff0c;继续咱们的预测。 老规矩&#xff0c;先给各位展示下百十个的神经网络蒙特卡洛统计频次图及部分号码的冷温热走势图。 最终&#xff0c;经过研判分析&#xff0c;2024年3月7日福彩3D的七…

人工蜂群算法

人工蜂群算法 人工蜂群算法&#xff08;Artificial Bee Colony Optimization,ABC&#xff09;是一种基于蜜蜂觅食行为的优化算法&#xff0c;由土耳其学者Karaboga于2005年提出&#xff0c;算法模拟蜜蜂的采蜜行为对优化问题进行求解。 算法原理 ABC算法的核心思想是将优化问…

C#中实现接口的一些小知识(C#用abstract或virtual来实现接口成员)

文章目录 不可用的修饰可用的修饰非抽象类实现接口抽象类实现接口抽象类与接口方法同名时一同实现 不可用的修饰 在C#中实现接口时&#xff0c;我们不能直接使用static或const来实现接口成员&#xff0c;因为接口中的成员默认都是实例成员&#xff0c;并且它们表示一种契约&am…

Go语言物联网开发安科瑞ADW300/4G电能表数据上传mqtt平台-电表接线到传输数据完整流程

电能表功能说明 ADW300是方便用户进行用电监测、集抄和管理&#xff0c;可灵活安装在配电箱中&#xff0c;可用于电力运维、环保监管等在线监测类平台中。我们本案例是用于工业售电公司对出售电的管理&#xff0c;设备可以监控用电情况、故障监控及警报&#xff0c;售电公司可…

灵魂指针,教给(二)

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 目录 一、数组名的理解 二、使用指针访问数组 三、一维数组传参本质 四、冒泡排序 五、二级指针 六、指针数组 七、指针数组…

JavaWeb笔记 --- 一JDBC

一、JDBC JDBC就是Java操作关系型数据库的一种API DriverManager 注册驱动可以不写 Class.forName("com.mysql.jdbc.Driver"); Connection Statement ResultSet PrepareStatement 密码输入一个SQL脚本&#xff0c;直接登录 预编译开启在url中 数据库连接池

SpringBoot+Vue实现el-table表头筛选排序(附源码)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;在笑大学牲 &#x1f39f;️个人主页&#xff1a;无所谓^_^ ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 前言 后台系统对table组件的需求是最常见的&#xff0c;不过element-ui的el…

智能指针基础知识【C++】【RAII思想 || unique_ptr || shared_ptrweak_ptr || 循环引用问题】

目录 一&#xff0c;为什么需要智能指针 二&#xff0c;内存泄露的基本认识 1. 内存泄露分类 2. 常见的内存检测工具 3&#xff0c;如何避免内存泄露 三&#xff0c;智能指针的使用与原理 1. RAII思想 2. 智能指针 &#xff08;1. unique_ptr &#xff08;2. shared_…

吴恩达deeplearning.ai:机器学习项目的完整周期伦理

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 文章目录 语音识别部署公平、偏见、伦理 这节博客中&#xff0c;我们主要看看构建一个机器学习的完整周期是什么&#xff0c;也就是说&#xff0c;当你想构建一个有价值的机器学习系统时&am…