C++学习笔记
Wily的CPP学习笔记
2022/06/27
- 标准库 bind 函数
private:
void timer_callback()
{
auto message = std_msgs::msg::String();
message.data = “Hello, world! “ + std::to_string(count_++);
RCLCPP_INFO(this->get_logger(), “Publishing: ‘%s’”, message.data.c_str());
publisher_->publish(message);
}
std::bind()
C++的类成员函数不能像普通函数那样用于回调,因为每个成员函数都需要有一个对象实例
去调用它。 通常情况下,要实现成员函数作为回调函数:一种过去常用的方法就是把该成员函数设计为静态成员函数(因为类的成员函数需要隐含的this指针 而回调函数没有办法提供),但这样做有一个缺点,就是会破坏类的结构性,因为静态成员函数只能访问该类的静态成员变量和静态成员函数,不能访问非静态的,要解决这个问题,可以把对象实例的指针或引用做为参数传给它
。 后面就可以靠这个对象实例的指针或引用访问非静态成员函数。另一种办法就是使用std::bind和std::function结合实现回调技术。
2022/06/29
- 关键字explicit
编译器是允许进行隐式转换(implicit conversion)的,如果现在在构造函数的前面加个关键字explicit,它的意思就是要告诉编译器,这个隐式转换不会再被允许了,只有当你有一个好的理由允许构造函数隐式转换,不然的话请把它们都声明为explicit,因为隐式转换容易导致错误,而这个错误往往不容易察觉。usleep
函数
能把线程挂起一段时间, 单位是微秒(千分之一毫秒)。本函数可暂时使程序停止执行。参数 micro_seconds 为要暂停的微秒数(us)。
头文件:unistd.h
语法:void usleep(int micro_seconds);
返回值: 无
2022/07/06
CLI 真的cool
- 编译过程
C++ 在linux下使用gcc编译器,该款编译器可以用于编译Go,Fortran,Ada,D等后端语言,编译过程如下:
- Pre-Processing //.i文件
文件展开,如纳入头文件
g++ -E test.cpp -o test.i- Compiling //.s文件
编译之后是汇编语言
g++ -S test.i -o test.s- Assembling //.o文件
编译之后是机器语言
g++ -c test.s -o test.o- Linking //bin
编译之后是可执行文件
g++ test.o -o test- 通常我们只用一个步骤:
g++ test.cpp -o test
- g++ 重要的编译参数
-g 编译带有调试信息的可执行文件
-O[n] n选择1-3 有优化代码的作用
-l 和-L 指定库文件|制定库文件路径(用于自己写的库)
-I 指定头文件搜索目录(头文件不在/usr/include时候)
-Wall 打印警告信息
-w 关闭警告信息
-std=c++11 设置编译标准
-o 制定输出文件名字
-D 定义宏(通常在代码中定义DEBUG的宏)
‘’‘ 和#ifdef DEBUG #endif搭配使用 ’‘’
- 生成库文件并且编译
- 静态库链接
汇编,生成swap.o文件,名称缺省
g++ swap.cpp -c -I../include
生成静态库libswap.a
ar rs libswap.a swap.o
编译
g++ main.cpp -Iinclude -Lsrc -lswap -o staticmain
2. 动态库链接直接生成
g++ swap.cpp -I../include -fPIC -shared -o libswap.so
该命令相当于:
g++ swap.cpp -I../include -c -fPIC
g++ -shared -o libswap.so swap.o编译
g++ main.cpp -Iinclude -Lsrc -lswap -o dynamicmain
- GDB调试器
vscode是使用GDN调试器来实现C/C++的调试工作的;
CIL指令:
- (gdb) help(h) #查看help
- (gdb) run(r) #重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件)
- (gdb)start # 单步执行,运行程序,停在第一行执行语句
- (gdb)list(l) # 查看源代码(list-n,从第n行开始查看代码。list+函数名字:查看具体函数)
- (gdb)set # 设置变量的值
- (gdb)next(n) # 单步调试(逐语句:跳入自定义函数内部执行)
- (gdb)step(s) # 单步调试(逐语句:跳入自定义函数内部执行)
- (gdb)print(p) # 打印数值以及地址
- (gdb)quit(q) # 退出gdb
- (gdb)break+num(b) # 在第num行设置断点
- (gdb) info breakpoints(ib) # 查看当前设置的所有断点
- (gdb) enable breakpoints # 启用断点
- (gdb) disable breakpoints # 禁用断点
Tips:- 编译程序时需要加上-g,之后才能用gdb进行调试:
gcc -g main.cpp -o main- 回车键可以重复上一个命令
- continue(c) 执行到下一个断点的位置
Cmake
- 基本语法格式:指令(参数1,参数2~~~)
参数用括弧括起来,参数之间使用空格或者分号隔开- 指令是大小写无关的,参数和变量是大小写相关的
- 变量使用doller方式取值,但是IF控制语句中是直接使用变量名
- set-显式的定义变量
set(VAR [VALUE][CACHE TYPE DOCSTRING [FORCE]])
set(SRC sayhello.cpp hello.cpp)- include_directories-向工程添加多个特定的头文件搜索路径
—->相当于指定g++编译器的-I参数- link_directories-向工程添加多个特定的库文件搜索路径
—–>相当于制定g++编译器的-L参数- add_library-生成库文件
add_library(libname [SHARED][STATIC][MODULE][EXCLUDE_FROM_ALL] source1 source2)
add_library(hello SHARED ${SRC})add_compile_options添加编译参数
add_compile_options()
add_compile_options(-wall -std=c++11 -o2)- add_excutable生成可执行文件
add_excutable(exname source1 source2)- tagrget_link_libraries为target添加需要链接的共享库
—->相同于g++编译器的-I参数
target_link_libraries(target library1<debug | optimized library2…>)
target_link_libraries(
main hello
)- add_subdirectory向当前工程添加存放源文件的子目录,并可以制定中间二进制和目标二进制存放的位置
12 aux_source_directory发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建元文件列表
aux_source_directory(dir VARIABLE)
定义SRC变量,他的值为当前目录下的所有源代码文件
aux_source_directory(. SRC)
编译SRC变量所代表的源代码文件,生成main可执行文件
add_excutable(main dollar{SRC})- Cmake常用变量
CMAKE_C_FLAGES gcc编译选项
CMAKE——CXX——FLAGES g++编译选项
CMAKE_BUILD_TYPE 编译类型(Debug Release)
add_definitions(“-Wall -g”) 和set (CMAKE_BUILD_TYPE Debug)作用相同- CMake编译规则
第一种: 包含源文件的子文件夹包含CMakeList.txt文件,主目录的CMakeList.txt通过add_subdirectory添加子目录即可
第二种:包含源文件的子文件夹未包含CMakeList.txt文件,子目录的编译规则要体现在主目录的CMakeList.txt中
构建方式采用外部构建:
步骤一:创建build mkdir build
步骤二:进入build文件夹 cd build
步骤三:编译上级目录的CMakeList.txt 生成Makefile和其他文件 cmake ..
步骤四:执行make命令,生成target makeVim
编译器
现在只会简单的插入,覆盖和退出,后续专门学习一下;
插入:i
覆盖: esc+shift+:+w
退出::q
设置tab为四个空格位置: :set ts=4
显示行号: :set nu
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Wizard!