当前位置:   article > 正文

C++常见语法汇总_c++语法

c++语法

目录

一.lambada表达式

auto func = [&epsilon](const TrajectoryPoint& tp,const double relative_time) {  
	return tp.relative_time() + epsilon < relative_time;};     
	auto it_lower = std::lower_bound(begin(), end(), relative_time, func); 
}//[]内的参数由外界获取,()内的参数由调用时传入
  • 1
  • 2
  • 3
  • 4

二.sizeof与strlen的区别以及typeof

1.sizeof

sizeof测量传入变量的类型的大小

2.strlen

strlen 参数为字符指针,从该指针所在位置开始,往后遍历,直到遇到‘\0’,不包含‘\0’。要求传入的必须是指针,不能传入string类型的对象

3.typeof

获取一个变量或表达式的类型

4.使用示例

char s[]=”hello world”;
sizeof(s) //12,包含了最后一个NULL字符
strlen(s) //11 ,不包含最后一个NULL字符

char *s=”hello world”;
sizeof(s) //8 ,字符类型指针所占内存大小
strlen(s) //11

string s=”hello world”;
sizeof(s) //32
strlen(s) //error,s不是一个字符串,需要strlen(s.c_str())或strlen(s.data());针对string s;strlen(s)根本就是错误的,因为strlen的参数是一个字符指针,如果想用strlen得到s字符串的长度,应该使用sizeof(s.c_str()),因为string的成员函数c_str()返回的是字符串的首地址。实际上,string类提供了自己的成员函数来得到字符串的容量和长度,分别是Capacity()和Length()。string封装了常用了字符串操作,所以在C++开发过程中,最好使用string代替C类型的字符串。
strlen(s.c_str()) //11
s.capacity() //15
s.length() //11
s.size() //11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

三.sort建议写法

std::sort(first_encounter_overlaps_.begin(),first_encounter_overlaps_.end(),[](const std::pair<OverlapType, hdmap::PathOverlap>& a,const std::pair<OverlapType, hdmap::PathOverlap>& b) 
{
    return a.second.start_s < b.second.start_s;
});  
  • 1
  • 2
  • 3
  • 4

四.std::fmod

%运算符用于int,fmod用于double/float等 取余

double NormalizeAngle(const double angle) {  
  double a = std::fmod(angle + M_PI, 2.0 * M_PI);  
  if (a < 0.0) {  
    a += (2.0 * M_PI);  
  }  
  return a - M_PI;  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

五.atan2与atan

atan2接收两个输入参数;atan只接收一个输入参数
atan2对象限敏感,根据两个参数判断它是属于哪个象限并给出对应的角度值,值域范围[-pi, pi];atan对象限不敏感,值域范围为(-pi/2, pi/2]

六.std::unique

该函数的作用是“去除”容器或者数组中相邻元素的重复出现的元素,注意
(1)这里的去除并非真正意义的erase,而是将重复的元素放到容器的末尾,返回值是去重之后的尾地址。
(2)unique针对的是相邻元素,所以对于顺序顺序错乱的数组成员,或者容器成员,需要先进行排序,可以调用std::sort()函数
学一学下面的unique的写法:

std::sort(polygon_points.begin(), polygon_points.end(),  
             [](const std::pair<STPoint, STPoint>& a,  
                const std::pair<STPoint, STPoint>& b) {  
               return a.first.t() < b.first.t();  
             });  
auto last = std::unique(polygon_points.begin(), polygon_points.end(),  
                           [](const std::pair<STPoint, STPoint>& a,  
                              const std::pair<STPoint, STPoint>& b) {  
                             return std::fabs(a.first.t() - b.first.t()) <  
                                     kStBoundaryDeltaT;  
                            });  
polygon_points.erase(last, polygon_points.end());  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

七. vector

1.初始化

vector<int> a(b); 
vector<int> a={1,2};
vector<int> a{1,2,3};
vector<int> list {1,2,3,4,5,6,7};//列表中元素的拷贝 然后 
vector<int> list3(list.begin()+2, list.end()-1); 本例中list3被初始化为{3,4,5,6} or vector<int> a(m,n); //包含m个n 
  • 1
  • 2
  • 3
  • 4
  • 5

2.常见操作

a.pop_back();  //删除最后一个数据,vector在不为空的前提下
a.erase(iterator first,iterator second);//删除指定范围内的数据:[first,second)遍历时需要注意,被删除的元素处iterator不能再继续使用
vector<int>::iterator iter = vec.begin() + 4; vec.erase(iter);//删除该容器第5个位置的数,erase不释放内存,只是将该位置初始化为默认值
std::remove(iterator first,iterator end,int val);//删除等于val的元素,返回最后一个!=val的元素下一个位置。     
std::vector<A> * ptr;//访问方式at,提供有界保护  
ptr->at(i);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.reverse

reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。

4.resize

是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。resize就是重新分配大小,reserve就是预留一定的空间

vector<vector<int>> double_arr(double_arr_size);
double_arr.emplace_back(10);
  • 1
  • 2

5.插入元素

emplace 
vector<int> a;
vector<vector <int>> s;
for (int i = 1; i <= 10; i++)
a.push_back(i);
s.emplace_back(a.begin(), a.end());
s.emplace(s.begin(), a.crbegin(), a.crend());//在s的开始位置插入
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

八.List

1.添加元素

emplace_back(可以直接在这里构造);//快速添加元素,例如reference_line_info_.emplace_back(reference_line_info类的构造参);例如:obstacles.emplace_back(new Obstacle(obstacle_id,prediction_obstacle.perception_obstacle(),trajectory, prediction_obstacle.priority().priority(), prediction_obstacle.is_static()));
push_front() //从头部插入元素
  • 1
  • 2

2.清除元素

clear();
  • 1

3.弹出元素

pop_back() //弹出尾部元素
pop_front() //弹出头部元素
  • 1
  • 2

4.访问元素

front() //访问第一个元素 【例】int &first=list.front();
back() //访问最后一个元素 【例】 int &last=list.back();
  • 1
  • 2

5.排序

reference_line_info_.sort([](a,b){return a.first<b.first});//对列表中的元素进行排序:
  • 1

九.std::string

1.初始化

string s="abcd";
string s("hello world");
string a(10,'a'); 
string s[2] = {"Tom", "Jerry"}; 
string a=b+c;//b,c为string
  • 1
  • 2
  • 3
  • 4
  • 5

2.字符串转整数

采用stoi函数

std::string str1 = "45";
std::string str2 = "3.14159";
std::string str3 = "31337 with words";
std::string str4 = "words and 2";
 
int myint1 = std::stoi(str1);
int myint2 = std::stoi(str2);
int myint3 = std::stoi(str3);
std::cout << "std::stoi(\"" << str1 << "\") is " << myint1 << '\n'; //std::stoi("45") is 45
std::cout << "std::stoi(\"" << str2 << "\") is " << myint2 << '\n'; //std::stoi("3.14159") is 3
std::cout << "std::stoi(\"" << str3 << "\") is " << myint3 << '\n'; //std::stoi("31337 with words") is 31337
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

采用atoi函数

string s="12";
int i=atoi(s.c_str());
  • 1
  • 2

采用istringstream方式

C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件。
istringstream类用于执行C++风格的串流的输入操作;
ostringstream类用于执行C风格的串流的输出操作;
stringstream类同时可以支持C风格的串流的输入输出操作。

istringstream s="12";
int i;
s>>i; //此时i的内容为12
  • 1
  • 2
  • 3

3.去除字符串某个元素

s.erase(s.begin());//去除字符串首个元素
s.erase(s.end()-1);//去除字符串最后面元素:
s.erase(s.begin()+i);//去除字符串下标为i的元素:官方提供的erase操作O(n)
  • 1
  • 2
  • 3

4.判断字符串是否存在某个元素

t.find(s)!=std::string::npos
  • 1

5.resize

s.resize(s.size()+10);//resize不会弄丢之前的内容
  • 1

6.字符串替换

s=s.replace(‘a’,'b');//将s中的'a'替换为‘b’
  • 1

7.字符串分割

s.split()
  • 1

8.字符串原地反转

reverse(s.begin(),s.end());
  • 1

9.字符串添加与删除

s.pop_back();
s.push_back('#');
  • 1
  • 2

十.stack

1.返回栈st的最顶层元素

stack<int> st;
int result=st.top();
  • 1
  • 2

十一.queue

1.基本操作

queue qu;
int result=qu.front();//返回queue qu的开头元素
qu.pop();//删除qu的开头元素
int result=qu.back();//返回qu的结尾元素
qu.push(x);//插入
  • 1
  • 2
  • 3
  • 4
  • 5

十二.deque

1.构造

deque<int> d1(d2begin(),d2.end());or deque<int> d1(d2); //用d2给d1初始化
deque<int> d2(10,100); //用10个100给d2初始化
  • 1
  • 2

2.赋值方式

deque<int> d1; 
push_back();//方式一 
operator = //方式二
d1.assign(d2.begin(),d2.end());//方式三     
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器的第一个数据
back(); //查看队尾元素
front(); //查看队首元素
d1.insert(d1.begin(),n,element);//在开头处插入n个element
d1.insert(d1.begin(),d2.begin(),d2.end());//同上
deque<int>::iterator it=d1.begin();
d1.erase(it);//删除值的方式 it为iterator的位置 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

十三.priority_queue

缺省情况下priority_queue利用max-heap(大顶堆)完成对元素的排序,这个大顶堆是以vector为表现形式的complete binary tree(完全二叉树)。

1.定义

class mycomparison {
    public:
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
            return lhs.second > rhs.second;
        }
};
priority_queue<pair<int, int>, vector<pair<int, int>>,mycomparison> pri_que;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

十四. cout设置精度

cout  <<setiosflags(ios::fixed)<< setprecision(2) << 1/1.0 << endl;
  • 1

十五.unordered_map

1.初始化

unordered_map<string,string> u_map={{"教程1","welcome"},{"教程2","hello"},{"教程3","world"}};
  • 1

2.基本用法

un_map.find('a')!=un_map.end();
unordered_map<string,int> example;
example.insert(pair<string,int>("xiaoming",18));
example.insert(pair<string,int>("xiaohua",19));
example.insert({xxx,xxx});
or example[xxx]=xxxx;
cout<<example["xiaohua"]<<endl; //ok
cout<<example.at("xiaoming")<<endl; //ok
cout<<example.at("yyf")<<endl;//terminate called after throwing an instance of 'std::out_of_range'
example.erase(key);//删除
example.erase(iter);
clear();//全部删除      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

十六.unordered_set

1.初始化

unordered_set<int> a(vec.begin(),vec.end()); //vec为vector类型对象 
a.insert(10); //insert返回的第一个元素为指向当前新添加的元素的迭代器,第二个参数为表示成功与否的true or false;  失败的话迭代器指向重复的元素。
  • 1
  • 2

十七.move

map_path_(std::move(std::vector<hdmap::MapPathPoint>(
reference_points.begin(), reference_points.end())));//给对象map_path_采用move方式进行赋值
  • 1
  • 2

十八.std::distance

std::size_t index=std::distance(xxx_list.cbegin(),iter);
  • 1

十九.std::lower_bound

std::lower_bound (accumulated_s.begin(), accumulated_s.end(),
s - look_backward));
  • 1
  • 2

二十.std::upper_bound

std::upper_bound(accumulated_s.begin(), accumulated_s.end(),s + look_forward));
  • 1

二十一.const用法

底层const进行拷贝时需要具有一置的属性,或者变量类型可以拷贝给const类型变量const int c=42;//指针常量,不能拷贝给非const类型的变量const int *p=c;//这里如果不加const就因属性不一致导致无法拷贝
//const初始化时就要赋值//const 常量的作用阈为本文件

int i=0;
const int *p=&i;//下层const,表示指针p无法改变变量i的值
int *const p1=&i;//上层const,表示指针p1指向变量i的内存空间后就不能再指向其他内存空间
  • 1
  • 2
  • 3

二十二.shared_ptr

1.申明+定义

auto map_msg = std::make_shared<MapMsg>();//无参构造//使用
or
std::make_shared<MapMsg> msg=nullptr;
msg.reset(new MapMsg());
msg->Process(xxxx);
relative_map_.Process(map_msg.get());//将std::make_shared<MapMsg>类型指针转变为MapMsg*
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

二十三.absl基本使用

1.按照规定字符分割string以及字符串拼接

std::string FindFirstExist(const std::string& dir, const std::string& files){
const std::vector<std::string> candidates = absl::StrSplit(files, '|');
  for (const auto& filename : candidates) {
    const std::string file_path = absl::StrCat(FLAGS_map_dir, "/", filename);
    if (cyber::common::PathExists(file_path)) {
      return file_path;
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

二十四.std::reverse()

std::reverse(points_.begin(), points_.end());  
  • 1

二十五.static_cast

将double类型变量转化为int,static_cast<double>(待转换的变量);
  • 1

二十六.std::string与std::string_view

二十七.std::map

map中的键是唯一的,默认按照键的值从小到大排序

1.定义与访问

map<string,int> mp;
mp['c']=20;//ok
cout<<mp['c']<<endl;//20
mp['c'] = 30;	//30覆盖了20 

map<typename1, typename2>::iterator it;
for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++){
		cout << it->first;	 
		cout << " "; 
		cout << it->second;
		cout << endl;
} //通过iterator来访问
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.查找与删除

find(key)返回键为key映射的迭代器,时间复杂度为O(logN),N为map中映射的个数

map<char, int> mp; 
mp['a'] = 222;
mp['b'] = 333;	
mp['c'] = 444;
map<char, int>::iterator it = mp.find('b');
cout << it->first << " " << it->second;//b 333
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

erase()有两种用法:1、删除单个元素。2、删除一个区间内所有的元素
删除单个元素:删除单个元素时间复杂度O(1)

map<char, int> mp; 
mp['a'] = 222;
mp['b'] = 333;	
mp['c'] = 444;
map<char, int>::iterator it = mp.find('b');
mp.erase(it);
for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++){
		cout << it->first << " " << it->second << endl;
}//a 222  c  444
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

mp.erase(key),key为要删除的映射的键。时间复杂度O(logN),N为map内元素的个数

map<char, int> mp; 
mp['a'] = 222;
mp['b'] = 333;	
mp['c'] = 444;
// map<char, int>::iterator it = mp.find('b');
// mp.erase(it);
mp.erase('b');
for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++){
		cout << it->first << " " << it->second << endl;
}//a 222  c  444
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

删除一个区间内所有的元素,mp.erase(first, last),其中,first为需要删除的区间的起始迭代器,last为需要删除的区间末尾迭代器的下一个地址,即为删除左闭右开的区间[first, last)。时间复杂度为O(last - first)

map<char, int> mp; 
mp['a'] = 222;
mp['b'] = 333;	
mp['c'] = 444;
map<char, int>::iterator it = mp.find('b');
mp.erase(it, mp.end()); //删除it之后的所有映射,即b 333和 c 444 
//mp.erase(it);
//mp.erase('b');
for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++){
cout << it->first << " " << it->second << endl;
}//a 222
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

size()用来获得map中映射的对数,复杂度为O(1)

clear()用来清空map中的所有元素,复杂度为O(N),N为map中元素个数

int转string

to_string

int i=20;
string s=i.to_string();
  • 1
  • 2

通过stringstream实现

int i=20;
ostirngstream os;
string s;
os.str("");
os<<i;
os>>s;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通过ostringstream实现

int i=10;
ostringstream os;
os<<i;
cout<<os.str()<<endl;
  • 1
  • 2
  • 3
  • 4

C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件。
istringstream类用于执行C++风格的串流的输入操作。
ostringstream类用于执行C风格的串流的输出操作。
stringstream类同时可以支持C风格的串流的输入输出操作。

getline()函数

//提前告诉代码会输入多少个字符串
int n;
cin>>n;
cin.ignore(1,'\n');
vector<string> vc(n);
string temp;
for(int i=0;i<n;i++)
{ 
    getline(cin,temp,'\n');
    vc[i]=temp;
} 
for(int i=0;i<n;i++)
	cout<<vc[i]<<endl;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
//不提前告诉会有多少个string
string s;
getline(cin,s,'\n');
stringstream ss;
ss<<s;
string temp;
vector<string> vec;
while(getline(ss,temp,' '))
{
    vec.push_back(temp);
}
for(int i=0;i<vec.size();i++)
{
    cout<<vec[i]<<endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

multimap

1、初始化

std::multimap<int, std::string> myMultimap;
  • 1

2、插入

myMultimap.insert(std::make_pair(1, "Apple"));
myMultimap.insert(std::make_pair(2, "Banana"));
myMultimap.insert(std::make_pair(2, "Blueberry"));
myMultimap.insert(std::make_pair(3, "Orange"));
  • 1
  • 2
  • 3
  • 4

3、删除

myMultimap.erase(myMultimap.begin());
  • 1

3、打印

for (const auto& pair : myMultimap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
  • 1
  • 2
  • 3

4、查询指定键

int keyToFind = 2;
    auto range = myMultimap.equal_range(keyToFind);
    std::cout << "Values with key " << keyToFind << ": " << std::endl;
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << it->second << std::endl;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

set用法

static用法

static C++ 中常用的修饰符,用来控制变量的存储方式和可见性。
static的会被存储到全局(静态)存储区。
1)静态局部变量
在修饰变量的时候,static 修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
a)静态局部变量在程序执行到该对象的声明处时被首次初始化(默认为0),即以后的函数调用不再进行初始化;
b)它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
不想被释放的时候,可以使用static修饰。比如修饰函数中存放在栈空间的数组,如果不想让这个数组在函数调用结束释放可以使用 static 修饰。
2)全局静态变量
static 修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。
3)static修饰函数
static 修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。
4)static在类中的使用
static可以修饰类的成员函数和成员变量。
被 static 修饰的方法统一属于类的静态资源,是类实例之间共享的。静态成员变量只存储一份供所有对象共用,使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
1、被static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个类来
2、被static修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要new出一个类来
静态成员的定义或声明要加个关键字 static。静态成员可以通过双冒号来使用即 <类名>::<静态成员名>。
a. 类的对象可以使用静态成员函数和非静态成员函数,但不能通过类名来调用类的非静态成员函数。
b. 静态成员函数中不能引用非静态成员。
因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间。反之,类的非静态成员函数可以调用用静态成员函数。但类的静态成员变量在使用前必须先初始化。
(1)静态成员函数中不能调用非静态成员。
(2)非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。
(3)静态成员变量使用前必须先初始化(如 int MyClass::m_nNumber = 0;),否则会在 linker 时出错。
静态数据成员
(1)静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
(2)静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
(3)静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。
(4)静态数据成员既可以通过对象名引用,也可以通过类名引用。
静态成员函数
(1)静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
(2)非静态成员函数有 this 指针,而静态成员函数没有 this 指针。
(3)静态成员函数主要用来访问静态数据成员而不能访问非静态成员。
5)static修饰类的对象
单例模式
InfoRouterSignal& InfoRouterSignal ::GetInstance() {//单例模式
static InfoRouterSignal tcc;
return tcc;
}

线程与进程

1、一个进程包含多个线程,如果该进程没有额外创建其他线程,那么该进程本身就是一个主线程
2、子线程可以共享主线程的资源(主线程的局部变量除外),他们通过共享的数据进行相互通信

pthread为c++11未引进thread之前适配

thread基本使用

#include <iostream>
#include <thread>
#include <mutex>
#include <stdlib.h>
int cnt = 20;
std::mutex m;
void t1(){
   while (cnt > 0)
   {    
       std::lock_guard<std::mutex> lockGuard(m);
      // std::m.lock();
       if (cnt > 0)
       {
           //sleep(1);
           --cnt;
           std::cout << cnt << std::endl;
       }
      // std::m.unlock();
   }
}

void t2(){
   while (cnt > 0)
   {
       std::lock_guard<std::mutex> lockGuard(m);
       // std::m.lock();
       if (cnt > 0)
       {
           --cnt;
           std::cout << cnt << std::endl;
       }
       // std::m.unlock();
   }
}

int main(void)
{
   std::thread th1(t1);
   std::thread th2(t2);
   th1.join();    //等待t1退出
   th2.join();    //等待t2退出
   std::cout << "here is the main()" << std::endl;
   return 0;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

https://segmentfault.com/a/1190000002655852

enum基本使用

修饰 struct

enum struct light{
red,yellow,blue};
//访问
cout<<light::red<<endl;

修饰class

enum class light{red,yellow,blue};//作用域位于class内部,不能隐式转换
//访问
cout<<light::red<<endl;

无修饰

enum light{red,yellow,blue};//作用域与enum同级,可以隐式转换
//访问
cout<<light::red<<red<<endl;

无修饰1

enum {red,yellow,blue};//作用域与enum同级,可以隐式转换
//访问
cout<<red<<endl;

std::chrono

#include <chrono>
auto startTime = high_resolution_clock::now();
auto stopTime = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stopTime - startTime);
  • 1
  • 2
  • 3
  • 4
#include<chrono>
using namespace chrono;
milliseconds start_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
milliseconds end_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
 cout << "耗时:" << end_time.count() - start_time.count() << "ms" << endl;
  • 1
  • 2
  • 3
  • 4
  • 5

ros中的时间计算

 double                timer;
 timer = ros::Time::now().toSec();
 double duration = (ros::Time::now().toSec() - timer) * 1000;
 cout<<"耗时:"<<duration<<"ms"<<endl;
  • 1
  • 2
  • 3
  • 4

define 、typedef、using

  • define只是简单的替换
  • typedef char welcome //c提供
  • using FootPrintPoints=Eigen::Matrix<double,4,2>;//c++提供

C++多态、向上转型、向下转型

  • 多态引入的意义

通过动态绑定来调用子类的virtual类型的成员函数,这样以后需要更改代码,只需要更换动态绑定的对象,即可完成后续所有功能开发

  • 向上转型
#include <iostream>
class Node {...};
class RootNode : public Node {...};
class SelfDrivingMode : public Node {...};
int main()
{
   SelfDrivingMode*  self_driving_mode   = new  SelfDrivingMode();
   std::map<int, Node*> sub_nodes_;                 // 子节点集合
   sub_nodes_.insert(std::make_pair(1, dynamic_cast<Node*>(self_driving_mode)));//向上转型
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

or

#include <iostream>

class Animal {
public:
    virtual void makeSound() {
        std::cout << "Animal makes a sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        std::cout << "Dog barks" << std::endl;
    }
};

int main() {
    Dog dog;
    Animal* animalPtr = &dog;  // 将派生类对象赋值给基类指针

    animalPtr->makeSound();  // 调用基类指针指向的对象的虚函数

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 向下转型
#include <iostream>

class Base {
public:
    virtual void display() {
        std::cout << "Base class" << std::endl;
    }
};

class Derived : public Base {
public:
    void display() override {
        std::cout << "Derived class" << std::endl;
    }

    void extraFunction() {
        std::cout << "Extra function in Derived class" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();  // 使用 Derived 对象的地址初始化 Base 指针

    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);  // 将 Base 指针转换为 Derived 指针

    if (derivedPtr) {
        derivedPtr->display();  // 调用 Derived 类中的 display 函数
        derivedPtr->extraFunction();  // 调用 Derived 类中的额外函数
    } else {
        std::cout << "Failed to cast basePtr to derivedPtr" << std::endl;
    }

    delete basePtr;

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/42234
推荐阅读
相关标签
  

闽ICP备14008679号