一些C++问题总结

Posted KAI-yq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些C++问题总结相关的知识,希望对你有一定的参考价值。

目录

指针

int  var = 20; 
int  *ip; 
ip=&var//将var地址传入指针
cout<<ip<<endl;//输出var地址
cout<<*ip<<endl;//输出var值

数据结构struct

定义:

struct type_name 
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
 object_names;

示例:

struct Books

   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
 book;

正常访问结构成员:

Books Book1;  
cout<<Book1.title<<endl;

作为函数参数:

void printBook(struct Books book);//定义函数
void printBook(struct Books book)
cout<<book.title<<endl;
//定义函数功能
printBook(Book1);//调用函数

定义指向结构的指针:

struct Books *struct_pointer;
struct_pointer = &Book1;
struct_pointer->title;

示例:

void printBook( struct Books *book );//定义函数
void printBook( struct Books *book )
cout<<book->tiitle<<endl;
//定义函数功能
printBook(&Book1);//调用函数

struct内嵌排序函数:

struct by_value

    bool operator()(smoothness_t const &left, smoothness_t const &right)
    
        return left.value < right.value;
    
;

与sort函数对比:

sort(intervals.begin(),intervals.end(),[](vector<int>a,vector<int>b)return a[1]<b[1];);
vector<Student> students = 2,"li lei", 1,"zhang jun", 4, "wang lei";
    sort(students.begin(), students.end(), [](Student& a, Student& b) -> bool 
        return a.ID < b.ID;
    );

strcpy函数

字符串复制

   strcpy( Book1.title, "C++ 教程");
   strcpy( Book1.author, "Runoob"); 
   strcpy( Book1.subject, "编程语言");
   Book1.book_id = 12345;

class GNSSSubscriber 
  public:
    GNSSSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size);
    GNSSSubscriber() = default;
    void ParseData(std::deque<GNSSData>& deque_gnss_data);

=default:会自动生成函数体;
deque 双端队列

? : ;

nums1[pos--] = nums1[m] > nums2[n]? nums1[m--]: nums2[n--];

?前面判断成立返回左边,不成立返回右边

#include “cmath”

cmath是c++语言中的标准库头文件。其中的 “c” 表示其中的函数是来自 C标准库,“math”表示为数学常用库函数。

#include “chrono”

c++11日期和时间库:chrono
std::chrono 主要包含两部分,std::chrono::duration 和 std::chrono::time_point,它们都是类模板,std::chrono::duration 表示时间间隔,std::chrono::time_point 表示时间中的一个点。

 std::chrono::steady_clock::time_point start_time=std::chrono::steady_clock::now();
 std::chrono::steady_clock::time_point end_time = std::chrono::steady_clock::now();
 std::chrono::duration<double> time_used = std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time);
 std::cout<<"\\n转换数据格式用时:"<<time_used.count()<<"秒。"<<std::endl;

start_time = std::chrono::steady_clock::now();
end_time = std::chrono::steady_clock::now();
time_used = std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time);
std::cout << "ICP计算用时: " << time_used.count() <<" 秒。" <<std::endl;

智能指针

std::shared_ptr<GNSSSubscriber> gnss_sub_ptr = std::make_shared<GNSSSubscriber>(nh, "/kitti/oxts/gps/fix", 1000000);

=号前就初始化了GNSSSubscriber类
例:std::shared_ptr<int>p = std::make_shared<int>(42);

make_shared 在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr,与智能指针一样,make_shared也定义在头文件memory中;

bar是一个智能指针,p是一个普通指针:
p = bar.get(); 后,bar并非被释放,也就相当于指针p和智能指针bar共同管理一个对象,所以就*p做的一切,都会反应到bar指向的对象上。

C++中int的除法

C++中int的除法总是向下取整
10/3=3
8/3=2

+=与-=以及.front

v.front() -= v.back();
v.front() = v.front() - v.back()

list.pop_front(); 删除list中的第一个位置的元素
list.front(); 获取list中的第一个元素变量

srand (time (NULL));

#include <ctime>

void test_rand(void)
    
    unsigned long n;
    srand((unsigned)time(NULL));
    for(int i = 0; i < 100; i++)
    
        n = rand();
        printf("d\\n", n);
    

用法: 它初始化随机种子,会提供一个种子,这个种子会对应一个随机数,如果使用相同的种子后面的 rand() 函数会出现一样的随机数,如: srand(1); 直接使用 1 来初始化种子。不过为了防止随机数每次重复,常常使用系统时间来初始化,即使用 time函数来获得系统时间,它的返回值为从 00:00:00 GMT, January 1, 1970 到现在所持续的秒数,然后将time_t型数据转化为(unsigned)型再传给srand函数,即: srand((unsigned) time(&t)); 还有一个经常用法,不需要定义time_t型t变量,即: srand((unsigned) time(NULL)); 直接传入一个空指针,因为你的程序中往往并不需要经过参数获得的数据。

进一步说明下:计算机并不能产生真正的随机数,而是已经编写好的一些无规则排列的数字存储在电脑里,把这些数字划分为若干相等的N份,并为每份加上一个编号用srand()函数获取这个编号,然后rand()就按顺序获取这些数字,当srand()的参数值固定的时候,rand()获得的数也是固定的,所以一般srand的参数用time(NULL),因为系统的时间一直在变,所以rand()获得的数,也就一直在变,相当于是随机数了。只要用户或第三方不设置随机种子,那么在默认情况下随机种子来自系统时钟。如果想在一个程序中生成随机数序列,需要至多在生成随机数之前设置一次随机种子。

即:只需在主程序开始处调用 srand((unsigned)time(NULL)); 后面直接用rand就可以了。不要在 for 等循环放置 srand((unsigned)time(NULL));

auto

auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型

stack<pair<int, int>> island;
island.push(i, j);
auto [r, c] = island.top();

static_cast

强制转换

int i;
float f = 166.55
i = static_cast<int>(f)

哈希表

map: #include<map>
unordered_map: #include<unordered_map>

平衡二叉树(AVL树):空树,或左右两个子树高度差绝对值不超过1。
二叉查找树(二叉排序树):根节点的值大于左子树任意一节点的值,小于右子树任意一节点的值。

map实现了红黑树(非严格平衡二叉查找树);
unordered_map实现了哈希表;

重载函数和重载运算符

1.函数重载

#include <iostream>
using namespace std;

class PrintData 
public:
  void Print(int i) 
    cout << "整数:" << i << endl;
  
  void Print(double f) 
    cout << "浮点数:" << f << endl;
  
  void Print(char c[]) 
    cout << "字符串:" << c << endl;
  
;

int main(void) 
  PrintData pd;
  pd.Print(5);
  pd.Print(5.12);
  char c[] = "Hello C++";
  pd.Print(c);
  return 0;

可以借助函数模板,将三次函数重载压缩成一个函数,本质是将类型(type)像值(value)一样通过参数化传递。

#include <iostream>
using namespace std;

template<typename T> void Swap(T &a, T &b) 
  T temp = a;
  a = b;
  b = temp;

int main() 
  int n1 = 100 , n2 = 200;
  Swap(n1, n2);
  
  double f1 = 12.5, f2 = 56.3;
  Swap(f1, f2);
  
  bool b1 = false , b2 = true;
  Swap(b1, b2);

template<class T>template<typename T>一样,
因为c++早期对模板支持不严谨,没有引入新关键字,后面才引入typename 

2.运算符重载 ( + )

#include <iostream>
using namespace std;

class Box 
public:
  Box operator+(const Box& b) 
    Box box;
    box.length = this->length + b.length;
    box.breadth = this->breadth + b.breadth;
    box.height = this->height + b.height;
    return box; 
  
private:
  double length;
  double breadth;
  double height;
;

int main() 
  Box box1;
  Box box2;
  Box box3;

  box3 = box1 + box2;
  return 0;

3.运算符重载( )

#include <iostream>
using namespace std;

class Distance 
private:
  int feet;
  int inches; 
public:
  Distance() 
  feet = 0;
  inches = 0;
  
  Distance(int f, int i) 
  feet = f;
  inches = i;
  
  //重载运算符
  Distance operator()(int a, int b, int c) 
    Distance D;
    D.feet = a + c + 10;
    D.inches = b + c + 100;
    return D;
  
  void DisplayDistance() 
    cout << "F:" << feet << "I:" << inches << endl;
  
;

int main() 
  Distance D1(11, 10), D2;
  D1.DisplayDistance();// 11,10

  D2 = D1(10, 10, 10);
  D2.DisplayDistance();//30,120
  return 0;
//不是创造新的调用函数方式,而是创建一个运算符函数

mutex

写法1,容易出现死锁

std::mutex m;
m.lock();
int a = getValue();
m.unlock();

写法2,更优雅,只在 范围内有效


std::mutex m;
std::lock_guard<std::mutex> lck(m);
int a = getValue();

thread基础用法

std::thread map_thread_;
bool update_;
std::atomic<bool> stop_true;

update_ = false;
stop_ = false;
map_thread_ = std::thread(&MapMatching::UpdateMap,this);

bool MapMatching::UpdateMap() 
  while(!stop_)
    if(update_) 
    ...
    update_ = false;
    
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  

d%的用法

用来代替“,”后面的变量 ,并以一个十进制的整数输出。
例:

repeat_reloc_init_ = config_reader.get<string>("repeat_reloc_init") == "true" ? true : false;
MLOG_INFO("repeat_reloc_init_ %d", repeat_reloc_init_);

无符号整型

1.size_t为尽可能大的无符号整型,在32位架构上是4字节,在64位架构上是8字节,在不同架构上进行编译时需要注意这个问题。

2.而int在不同架构下都是4字节,与size_t不同;且int为带符号数,size_t为无符号数。

3.uint32_t
u:代表 unsigned 即无符号,即定义的变量不能为负数;
int:代表类型为 int 整形;
32:代表四个字节,即为 int 类型;
_t:代表用 typedef 定义的;
整体代表:用 typedef 定义的无符号 int 型宏定义;

inline void sort_hdmap(const MLAHdmapInfo &hdmap,
    std::map<uint32_t, MLAHdmapInfo> &multi_layer_hdmap) 
    

acess函数,判断文件能不能读写

#include <unistd.h>

std::string lidar_yaml_path = calib_file_path_ + "/calibration/lidar.yaml";
if(access(lidar_yaml_path.c_str(),R_OK)!=0)

    err_msg_ = "lidar.yaml not exist !";
    is_input_ok_ = false;

用.c_str()的原因为:access需要传进一个char型指针

static inline int access(const char* path, int mode)  return _access(path, mode); 

另外,R_OK表示是否可读检查:
#define	R_OK	4		/* Test for read permission.  */
#define	W_OK	2		/* Test for write permission.  */
#define	X_OK	1		/* Test for execute permission.  */
#define	F_OK	0		/* Test for existence.  */
如果文件具有指定的访问权限,则函数返回0;如果文件不存在或者不能访问指定的权限,则返回-1.

.c_str()用法详解:

#include<csting>
using namespace std;
 
int main()

    //string-->char*
    //c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同
    //这个数组的数据是临时的,当有一个改变这些数据的成员函数被调用后,其中的数据就会失效。
    //因此要么现用先转换,要么把它的数据复制到用户自己可以管理的内存中
    
    const char *c;
    string s = "1234";
    c = s.c_str();
    cout<<c<<endl;
    s = "abcde";
    cout<<c<<endl;

输出结果:

1234
abcde

union类

https://blog.csdn.net/qq_45611002/article/details/119675452
https://blog.csdn.net/std7879/article/details/125001689

explicit

在不加explicit之前,隐式的转换为类的类型

union MSFS

    MSFS() : status_all_(0) 
    MSFS(int64_t val) : status_all_(val) 

MSFS detailed_status_ = 0l;//0l为长整型,long int

加explicit之后,要显式的转换为类的类型

union MSFS

    MSFS() : status_all_(0) 
    explicit MSFS(int64_t val) : status_all_(val) 

MSFS detailed_status_ = (MSFS)0l;
或者
MSFS detailed_status_ = MSFS(0l);

https://blog.csdn.net/Currybeefer/article/details/113416125?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-113416125-blog-116211624.pc_relevant_multi_platform_featuressortv2removedup&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-113416125-blog-116211624.pc_relevant_multi_platform_featuressortv2removedup&utm_relevant_index=2

以上是关于一些C++问题总结的主要内容,如果未能解决你的问题,请参考以下文章

PAT归纳总结——关于C++输入输出格式问题的一些总结

为啥我不能推送这个最新的 Git 子树?

树形dp总结

一些C++问题总结

c++中的智能指针

C++编程新手容易犯的10种编程错误