C++常见知识点总结

本文总结了C++中的重要知识点,包括数据类型如枚举和结构,类型转换如static_cast和dynamic_cast,字符串处理,switch case用法,输出显示,以及指针和引用的区别与应用。特别强调了引用作为函数参数和返回值的优势,以及指针操作内存的潜在风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据类型

  1. 枚举类型enum
    enum MotorIndex {
      kLeftMotor = 0,
      kRightMotor = 1,
    };

枚举常量必须是整数类型,可以当变量直接使用。

  1. struct结构
   struct MotorStatus {
      float current;
      int16_t temperature;
      int16_t temperature_MCU;
      int16_t rpm;
      int32_t counter;
      int32_t counter_offset;
      uint8_t status;
      bool counter_reset;
      //类变量初始化
      MotorStatus() :
        rpm(0), counter(0), status(0), counter_reset(false)
      { }
    };
    MotorStatus motorstatus[2];
    motorstatus[0].current = 0;
  1. size_t
    使用size_t可能会提高代码的可移植性、有效性或者可读性。
    例:
    size_t size=sizeof(i);//用sizeof操作得到变量i的类型的大小,
    有时候会使用unsigned int,但是它有可能会影响设备的性能。

常见类型转换

  1. static_castdynamic_cast:
    前者提供的是编译时期的静态类型检测,后者提供的是运行时检测.dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全
    static_cast: 1)完成基础数据类型,2)同一个继承体系中类型的转换 3)任意类型与空指针类型void*之间的转换。
    dynamic_cast:使用多态的场景,增加了一层对真实调用对象类型的检查

  2. const_cast
    用于取出const属性,把const类型的指针变为非const类型的指针,

  3. reinterpret_cast
    数据的二进制形式重新解释,但是不改变其值。这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。
    如:

    int i; char *ptr="hello freind!"; i=reinterpret_cast<int>(ptr);
    static_cast<int>()....类似
  1. c_str()
    string.c_str()返回字符串指针 (ROS_INFO中经常用来输出%s)
  2. strcpymemcpy
    strcpy和memcpy都是标准C库函数,它们有下面的特点。
    strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
    已知strcpy函数的原型是:char* strcpy(char* dest, const char* src);
    memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
    这两个函数也可以作为类型转换的使用。
  3. atoi()和stoi()
    atoi()的参数是 const char* ,因此对于一个字符串str我们必须调用 c_str()的方法把这个string转换成 const char类型的,而stoi()的参数是const string,不需要转化为 const char*;
    stoi()会做范围检查,默认范围是在int的范围内的,如果超出范围的话则会runtime error
    而atoi()不会做范围检查,如果超出范围的话,超出上界,则输出上界,超出下界,则输出下界
  4. to_string()
    std::to_string(1);
    将数值转化为字符串。返回对应的字符串。

字符串分割

  1. strtok函数
buf_spilt[0] = strtok(buf_c, delim1); 
data_n = strtok(NULL, delim1);

参数与返回值都是char*,第一次使用时会分割出字符并返回左侧的字符串,并会保存分割位置的指针,再次使用并给出NULL参数,会继续进行分割,如果为发现分隔符,则返回NULL。此函数设计优劣都很明显,使用需谨慎。

    //一个连续分割的例子
    int datacheck = 1;
    char *data_n = new char[20];
    char *buf_c = new char[200];
    char const *delim1 = "\r";
    char const *delim2 = "=";
    std::vector<std::string> buf_spilt(27);
    strcpy(buf_c, buf_driver.c_str());
    buf_spilt[0] = strtok(buf_c, delim1); 
    for (int i = 1; i < 26; ++i)
    {
      // ROS_INFO("%s", buf_spilt[i-1].c_str());
      data_n = strtok(NULL, delim1);
      if (data_n != NULL)
      {
        buf_spilt[i] = data_n;
      }
      else {
        datacheck = 0;
        i = 26;
      }
    }
    // ROS_INFO("%s", buf_spilt[25].c_str());
    if (datacheck == 1)
    {
      for (int i = 1; i < 26; i+=2)
      {
        char *buf_n = new char[20];
        strcpy(buf_n, buf_spilt[i].c_str());
        char *temp2 = strtok(buf_n, delim2);
        if (temp2 == data_type[(i-1)/2])
        {
          temp2 = strtok(NULL, delim2);
          num[(i-1)/2] = atoi(temp2);
        }
      }
    }
  1. 使用find与string手写
std::vector<std::string> iqr::CasterHardware::BufferSpilt(std::string buf_driver, const char* delim) {
  std::vector<std::string> data_type;
  data_type.push_back(buf_driver);
  int data_start = 0, data_stop = 0, i = 0;
  while(data_stop != -1)
  {
    data_stop = buf_driver.find(delim, data_start);
    // ROS_INFO("%i", data_stop);  
    if (data_stop != -1)
    {
      data_type.push_back(buf_driver.substr(data_start, data_stop));
      // ROS_INFO("%s", data_type[i].c_str());
      data_start = data_stop+1;
      i++;
    }
    if (i != 0 && data_stop == -1)
    {
      data_type.push_back(buf_driver.substr(data_start));
      // ROS_INFO("%s", data_type[i].c_str());
    }
  }
  for (int i = 0; i < data_type.size(); ++i)
  {
    ROS_INFO("%s", data_type[i].c_str());
  }
  return data_type;
}
void split(const string& s, vector<string>& tokens, const string& delimiters = " ")
{
  string::size_type lastPos = s.find_first_not_of(delimiters, 0);
  string::size_type pos = s.find_first_of(delimiters, lastPos);
  while (string::npos != pos || string::npos != lastPos) {
    tokens.push_back(s.substr(lastPos, pos - lastPos));
    lastPos = s.find_first_not_of(delimiters, pos);
    pos = s.find_first_of(delimiters, lastPos);
  }
}
  1. C++ 11之后可用正则表达式
std::string text = "Quick brown fox.";
std::regex ws_re("\\s+");
std::vector<std::string> v(std::sregex_token_iterator(text.begin(),    
   text.end(), ws_re, -1),std::sregex_token_iterator());
for(auto&& s: v)
  std::cout<<s<<"\n";

更高版本会有更多的实现方式,考虑开发环境适合版本使用适合方法。

switch case区分字符串

C++中只能以数字类型作为参数。
可以使用map的方式,然后进行数据处理。

输出显示

  1. 长字符串
 for (int i = 0; i < buf_driver.size(); i++) {
      ROS_INFO("%c", *(buf_driver.c_str()+i));
    }

指针与引用

int m; 
int &n = m;

n 相当于 m 的别名, 既不是m的拷贝,也不是指向 m 的指针,n就是 m 。

引用的规则:

  1. 用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
  2. NULL 引用,引用必须与合法的存储单元关联(指针则可以是 NULL)。
  3. 引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。

以下示例程序中,k 被初始化为i的引用。
语句 k = j 并不能将 k 修改成为j的引用,只是把k的值改变成为 6。
由于 k 是 i 的引用,所以i的值也变成了 6。

int i = 5; 
int j = 6; 
int &k = i; 
k = j; // k 和 i 的值都变成了 6;

引用的主要功能是传递函数的参数和返回值。

C++ 语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。

以下是"值传递"的示例程序。

由于 Func1 函数体内的 x 是外部变量 n 的一份拷贝,改变 x 的值不会影响 n, 所以 n 的值仍然是 0。

void Func1(int x) 
{ 
    x = x + 10; 
} 
... 
int n = 0; 
Func1(n); 
cout << "n = " << n << endl; // n = 0 

以下是"指针传递"的示例程序。

由于 Func2 函数体内的 x 是指向外部变量 n 的指针,改变该指针的内容将导致 n 的值改变,所以 n 的值成为 10。

void Func2(int *x) 
{ 
    (* x) = (* x) + 10; 
} 
... 
int n = 0; 
Func2(&n); 
cout << "n = " << n << endl; // n = 10

以下是"引用传递"的示例程序。

由于 Func3 函数体内的 x 是外部变量 n 的引用,x 和 n 是同一个东西,改变 x 等于改变 n,所以 n 的值成为 10。

void Func3(int &x) 
{ 
    x = x + 10; 
} 
... 
int n = 0; 
Func3(n); 
cout << "n = " << n << endl; // n = 10 

指针能够毫无约束地操作内存中的任何东西,尽管指针功能强大,但是非常危险。

如果的确只需要借用一下某个对象的"别名",那么就用"引用",而不要用"指针",以免发生意外。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值