Wily的CPP学习笔记

2022/06/27

  1. 标准库 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

  1. 关键字explicit
    编译器是允许进行隐式转换(implicit conversion)的,如果现在在构造函数的前面加个关键字explicit,它的意思就是要告诉编译器,这个隐式转换不会再被允许了,只有当你有一个好的理由允许构造函数隐式转换,不然的话请把它们都声明为explicit,因为隐式转换容易导致错误,而这个错误往往不容易察觉。
  2. usleep函数
    能把线程挂起一段时间, 单位是微秒(千分之一毫秒)。本函数可暂时使程序停止执行。参数 micro_seconds 为要暂停的微秒数(us)。
    头文件: unistd.h
    语法: void usleep(int micro_seconds);
    返回值: 无

2022/07/06CLI 真的cool

  1. 编译过程
    C++ 在linux下使用gcc编译器,该款编译器可以用于编译Go,Fortran,Ada,D等后端语言,编译过程如下:
    1. Pre-Processing //.i文件文件展开,如纳入头文件
      g++ -E test.cpp -o test.i
    2. Compiling //.s文件编译之后是汇编语言
      g++ -S test.i -o test.s
    3. Assembling //.o文件编译之后是机器语言
      g++ -c test.s -o test.o
    4. Linking //bin编译之后是可执行文件
      g++ test.o -o test
    5. 通常我们只用一个步骤:
      g++ test.cpp -o test
  2. g++ 重要的编译参数
    -g 编译带有调试信息的可执行文件
    -O[n] n选择1-3 有优化代码的作用
    -l 和-L 指定库文件|制定库文件路径(用于自己写的库)
    -I 指定头文件搜索目录(头文件不在/usr/include时候)
    -Wall 打印警告信息
    -w 关闭警告信息
    -std=c++11 设置编译标准
    -o 制定输出文件名字
    -D 定义宏(通常在代码中定义DEBUG的宏)
    ‘’‘ 和#ifdef DEBUG #endif搭配使用 ’‘’
  3. 生成库文件并且编译
    1. 静态库链接

    汇编,生成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

  4. GDB调试器
    vscode是使用GDN调试器来实现C/C++的调试工作的;
    CIL指令:
    1. (gdb) help(h) #查看help
    2. (gdb) run(r) #重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件)
    3. (gdb)start # 单步执行,运行程序,停在第一行执行语句
    4. (gdb)list(l) # 查看源代码(list-n,从第n行开始查看代码。list+函数名字:查看具体函数)
    5. (gdb)set # 设置变量的值
    6. (gdb)next(n) # 单步调试(逐语句:跳入自定义函数内部执行)
    7. (gdb)step(s) # 单步调试(逐语句:跳入自定义函数内部执行)
    8. (gdb)print(p) # 打印数值以及地址
    9. (gdb)quit(q) # 退出gdb
    10. (gdb)break+num(b) # 在第num行设置断点
    11. (gdb) info breakpoints(ib) # 查看当前设置的所有断点
    12. (gdb) enable breakpoints # 启用断点
    13. (gdb) disable breakpoints # 禁用断点
      Tips:
    14. 编译程序时需要加上-g,之后才能用gdb进行调试:
      gcc -g main.cpp -o main
    15. 回车键可以重复上一个命令
    16. continue(c) 执行到下一个断点的位置
  5. Cmake
    1. 基本语法格式:指令(参数1,参数2~~~)
      参数用括弧括起来,参数之间使用空格或者分号隔开
    2. 指令是大小写无关的,参数和变量是大小写相关的
    3. 变量使用doller方式取值,但是IF控制语句中是直接使用变量名
    4. set-显式的定义变量
      set(VAR [VALUE][CACHE TYPE DOCSTRING [FORCE]])
      set(SRC sayhello.cpp hello.cpp)
    5. include_directories-向工程添加多个特定的头文件搜索路径
      —->相当于指定g++编译器的-I参数
    6. link_directories-向工程添加多个特定的库文件搜索路径
      —–>相当于制定g++编译器的-L参数
    7. add_library-生成库文件
      add_library(libname [SHARED][STATIC][MODULE][EXCLUDE_FROM_ALL] source1 source2)
      add_library(hello SHARED ${SRC})
    8. add_compile_options添加编译参数
      add_compile_options()
      add_compile_options(-wall -std=c++11 -o2)
    9. add_excutable生成可执行文件
      add_excutable(exname source1 source2)
    10. tagrget_link_libraries为target添加需要链接的共享库
      —->相同于g++编译器的-I参数
      target_link_libraries(target library1<debug | optimized library2…>)
      target_link_libraries(
      main hello
      )
    11. add_subdirectory向当前工程添加存放源文件的子目录,并可以制定中间二进制和目标二进制存放的位置
      12 aux_source_directory发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建元文件列表
      aux_source_directory(dir VARIABLE)
      定义SRC变量,他的值为当前目录下的所有源代码文件
      aux_source_directory(. SRC)
      编译SRC变量所代表的源代码文件,生成main可执行文件
      add_excutable(main dollar{SRC})
  6. Cmake常用变量
    CMAKE_C_FLAGES gcc编译选项
    CMAKE——CXX——FLAGES g++编译选项
    CMAKE_BUILD_TYPE 编译类型(Debug Release)
    add_definitions(“-Wall -g”) 和set (CMAKE_BUILD_TYPE Debug)作用相同
  7. CMake编译规则
    第一种: 包含源文件的子文件夹包含CMakeList.txt文件,主目录的CMakeList.txt通过add_subdirectory添加子目录即可
    第二种:包含源文件的子文件夹未包含CMakeList.txt文件,子目录的编译规则要体现在主目录的CMakeList.txt中
    构建方式采用外部构建:
    步骤一:创建build mkdir build
    步骤二:进入build文件夹 cd build
    步骤三:编译上级目录的CMakeList.txt 生成Makefile和其他文件 cmake ..
    步骤四:执行make命令,生成target make
  8. Vim 编译器
    现在只会简单的插入,覆盖和退出,后续专门学习一下;
    插入:i
    覆盖: esc+shift+:+w
    退出::q
    设置tab为四个空格位置: :set ts=4
    显示行号: :set nu